@fluxerjs/core 1.0.9 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/LICENSE +203 -0
  2. package/dist/{Channel-ICWNKXBR.mjs → Channel-4WVFDOCG.mjs} +4 -1
  3. package/dist/{ClientUser-WWXUMO5O.mjs → ClientUser-PXAAKR2P.mjs} +1 -1
  4. package/dist/Guild-FMBCTAV4.mjs +12 -0
  5. package/dist/{GuildBan-M4PA3HAA.mjs → GuildBan-7CXLTPKY.mjs} +1 -1
  6. package/dist/GuildMember-43B5E5CH.mjs +9 -0
  7. package/dist/Message-OFIVTTAZ.mjs +9 -0
  8. package/dist/{MessageReaction-XRPYZDSC.mjs → MessageReaction-AYSOCOMX.mjs} +2 -1
  9. package/dist/{Role-SVLWIAMN.mjs → Role-5MWSGL66.mjs} +1 -1
  10. package/dist/Webhook-RWDDYW2Q.mjs +10 -0
  11. package/dist/{chunk-GCIJYVRC.mjs → chunk-4F765HVV.mjs} +54 -3
  12. package/dist/chunk-AH7KYH2Z.mjs +50 -0
  13. package/dist/{chunk-53Y37KRG.mjs → chunk-CJVQNARM.mjs} +44 -10
  14. package/dist/chunk-DQ4TNBPG.mjs +63 -0
  15. package/dist/chunk-DUQAD7F6.mjs +173 -0
  16. package/dist/chunk-FRVZ7D6D.mjs +293 -0
  17. package/dist/{chunk-HBF5QEDH.mjs → chunk-K6NLD6SB.mjs} +23 -1
  18. package/dist/chunk-PM2IUGNR.mjs +29 -0
  19. package/dist/chunk-RWFKZ3DF.mjs +413 -0
  20. package/dist/{chunk-RCP27MRC.mjs → chunk-UXIF75BV.mjs} +3 -0
  21. package/dist/chunk-V6T5VMWD.mjs +26 -0
  22. package/dist/{chunk-DSPSRPHF.mjs → chunk-V7LPVPGH.mjs} +123 -18
  23. package/dist/chunk-X6K3ZD62.mjs +53 -0
  24. package/dist/index.d.mts +603 -113
  25. package/dist/index.d.ts +603 -113
  26. package/dist/index.js +1335 -426
  27. package/dist/index.mjs +189 -125
  28. package/package.json +8 -8
  29. package/dist/Guild-TM6YGJWB.mjs +0 -10
  30. package/dist/GuildMember-RZWZ3OCG.mjs +0 -7
  31. package/dist/Message-6IYEYSV6.mjs +0 -7
  32. package/dist/Webhook-32VJD4AL.mjs +0 -7
  33. package/dist/chunk-FJS5FBXO.mjs +0 -233
  34. package/dist/chunk-GFUJVQ7L.mjs +0 -64
  35. package/dist/chunk-SQVCCSNN.mjs +0 -41
  36. package/dist/chunk-X77DFNE3.mjs +0 -136
package/dist/index.d.mts CHANGED
@@ -1,14 +1,18 @@
1
1
  import * as _fluxerjs_types from '@fluxerjs/types';
2
- import { APIWebhook, APIWebhookUpdateRequest, APIWebhookTokenUpdateRequest, APIChannel, APIChannelPartial, ChannelType, APIMessageAttachment, MessageType, APIEmbed, APIMessageSticker, APIMessageReaction, APIMessageReference, APIMessageSnapshot, APIMessageCall, APIMessage, APIUserPartial, APIGuildMember, APIRole, APIGuild, APIGuildAuditLog, APIGuildPartial, APIInvite, APIBan, GatewayReactionEmoji, GatewayMessageReactionAddDispatchData, GatewayMessageReactionRemoveDispatchData, GatewayPresenceUpdateData, GatewaySendPayload, Routes, GatewayMessageReactionRemoveAllDispatchData, GatewayMessageReactionRemoveEmojiDispatchData, GatewayVoiceStateUpdateDispatchData, GatewayVoiceServerUpdateDispatchData, APIEmoji, APISticker } from '@fluxerjs/types';
3
- export { GatewayOpcodes, Routes } from '@fluxerjs/types';
2
+ import { APIEmbed, APIWebhook, APIWebhookUpdateRequest, APIWebhookTokenUpdateRequest, APIChannelOverwrite, APIChannel, APIChannelPartial, ChannelType, GatewayReactionEmoji, GatewayMessageReactionAddDispatchData, GatewayMessageReactionRemoveDispatchData, APIMessageAttachment, MessageType, APIMessageSticker, APIMessageReaction, APIMessageReference, APIMessageSnapshot, APIMessageCall, APIMessage, APIUserPartial, APIGuildMember, APIRole, APIBan, GuildFeature, GuildVerificationLevel, DefaultMessageNotifications, GuildExplicitContentFilter, GuildMFALevel, APIGuild, APIGuildAuditLog, APIGuildPartial, APIInvite, GatewayPresenceUpdateData, GatewayMessageReactionRemoveAllDispatchData, GatewayMessageReactionRemoveEmojiDispatchData, GatewayVoiceStateUpdateDispatchData, GatewayVoiceServerUpdateDispatchData, GatewayGuildEmojisUpdateDispatchData, GatewayGuildStickersUpdateDispatchData, GatewayGuildIntegrationsUpdateDispatchData, GatewayGuildScheduledEventCreateDispatchData, GatewayGuildScheduledEventUpdateDispatchData, GatewayGuildScheduledEventDeleteDispatchData, GatewayChannelPinsUpdateDispatchData, GatewayPresenceUpdateDispatchData, GatewayWebhooksUpdateDispatchData, GatewaySendPayload, Routes, APIEmoji, APISticker } from '@fluxerjs/types';
3
+ export { GatewayOpcodes, MessageAttachmentFlags, Routes } from '@fluxerjs/types';
4
4
  import { Collection } from '@fluxerjs/collection';
5
5
  import { EmbedBuilder } from '@fluxerjs/builders';
6
6
  export { AttachmentBuilder, EmbedBuilder, MessagePayload } from '@fluxerjs/builders';
7
7
  import { EventEmitter } from 'events';
8
+ import { PermissionResolvable } from '@fluxerjs/util';
9
+ export { PermissionFlags, PermissionResolvable, PermissionString, PermissionsBitField, resolveTenorToImageUrl } from '@fluxerjs/util';
8
10
  import { REST } from '@fluxerjs/rest';
9
11
  import { WebSocketManager } from '@fluxerjs/ws';
10
12
 
13
+ /** Base class for all Fluxer structures. Provides the client reference. */
11
14
  declare abstract class Base {
15
+ /** The client instance this structure belongs to. */
12
16
  abstract readonly client: Client;
13
17
  }
14
18
 
@@ -25,23 +29,102 @@ declare class MessageManager {
25
29
  /**
26
30
  * Fetch a message by ID from this channel.
27
31
  * @param messageId - Snowflake of the message
28
- * @returns The message, or null if not found
32
+ * @returns The message
33
+ * @throws FluxerError with MESSAGE_NOT_FOUND if the message does not exist
29
34
  */
30
- fetch(messageId: string): Promise<Message | null>;
35
+ fetch(messageId: string): Promise<Message>;
36
+ }
37
+
38
+ interface MessageCollectorOptions {
39
+ /** Filter function. Return true to collect the message. */
40
+ filter?: (message: Message) => boolean;
41
+ /** Max duration in ms. Collector stops when time expires. */
42
+ time?: number;
43
+ /** Max messages to collect. Collector stops when limit reached. */
44
+ max?: number;
45
+ }
46
+ type MessageCollectorEndReason = 'time' | 'limit' | 'user';
47
+ interface MessageCollectorEvents {
48
+ collect: [message: Message];
49
+ end: [collected: Collection<string, Message>, reason: MessageCollectorEndReason];
50
+ }
51
+ /**
52
+ * Collects messages in a channel. Use channel.createMessageCollector().
53
+ * @example
54
+ * const collector = channel.createMessageCollector({ filter: m => m.author.id === userId, time: 10000 });
55
+ * collector.on('collect', m => console.log(m.content));
56
+ * collector.on('end', (collected, reason) => console.log(`Stopped: ${reason}`));
57
+ */
58
+ declare class MessageCollector extends EventEmitter {
59
+ readonly client: Client;
60
+ readonly channelId: string;
61
+ readonly options: Required<MessageCollectorOptions>;
62
+ readonly collected: Collection<string, Message>;
63
+ private _timeout;
64
+ private _ended;
65
+ private _listener;
66
+ constructor(client: Client, channelId: string, options?: MessageCollectorOptions);
67
+ stop(reason?: MessageCollectorEndReason): void;
68
+ on<K extends keyof MessageCollectorEvents>(event: K, listener: (...args: MessageCollectorEvents[K]) => void): this;
69
+ emit<K extends keyof MessageCollectorEvents>(event: K, ...args: MessageCollectorEvents[K]): boolean;
31
70
  }
32
71
 
33
- /** Options for sending a message via webhook. */
72
+ /** File data for message attachment uploads (Buffer supported in Node.js). */
73
+ interface MessageFileData {
74
+ name: string;
75
+ data: Blob | ArrayBuffer | Uint8Array | Buffer;
76
+ filename?: string;
77
+ }
78
+ /** Attachment metadata for file uploads (id matches FormData index). */
79
+ interface MessageAttachmentMeta {
80
+ id: number;
81
+ filename: string;
82
+ title?: string | null;
83
+ description?: string | null;
84
+ /** MessageAttachmentFlags: IS_SPOILER (8), CONTAINS_EXPLICIT_MEDIA (16), IS_ANIMATED (32) */
85
+ flags?: number;
86
+ }
87
+ /** Options for sending a message (content, embeds, files). Used by Message.send, Channel.send, ChannelManager.send. */
88
+ type MessageSendOptions = string | {
89
+ content?: string;
90
+ embeds?: (APIEmbed | EmbedBuilder)[];
91
+ /** File attachments. When present, request uses multipart/form-data. */
92
+ files?: MessageFileData[];
93
+ /** Attachment metadata for files (id = index). Use when files are provided. */
94
+ attachments?: MessageAttachmentMeta[];
95
+ };
96
+
97
+ /** File data for webhook attachment uploads (Buffer supported in Node.js). */
98
+ interface WebhookFileData {
99
+ name: string;
100
+ data: Blob | ArrayBuffer | Uint8Array | Buffer;
101
+ filename?: string;
102
+ }
103
+ /** Attachment metadata for webhook file uploads (id matches FormData index). */
104
+ interface WebhookAttachmentMeta {
105
+ id: number;
106
+ filename: string;
107
+ title?: string | null;
108
+ description?: string | null;
109
+ /** MessageAttachmentFlags: IS_SPOILER (8), CONTAINS_EXPLICIT_MEDIA (16), IS_ANIMATED (32) */
110
+ flags?: number;
111
+ }
112
+ /** Options for sending a message via webhook. Aligns with WebhookMessageRequest in the API. */
34
113
  interface WebhookSendOptions {
35
- /** Message text content */
114
+ /** Message text content (up to 2000 characters) */
36
115
  content?: string;
37
- /** Embed objects (use EmbedBuilder.toJSON()) */
38
- embeds?: Array<Record<string, unknown>>;
39
- /** Override the webhook's default username */
116
+ /** Embed objects. Use EmbedBuilder or APIEmbed; EmbedBuilder is serialized automatically. */
117
+ embeds?: (APIEmbed | EmbedBuilder)[];
118
+ /** Override the webhook's default username for this message */
40
119
  username?: string;
41
- /** Override the webhook's default avatar URL */
120
+ /** Override the webhook's default avatar URL for this message */
42
121
  avatar_url?: string;
43
122
  /** Text-to-speech */
44
123
  tts?: boolean;
124
+ /** File attachments. When present, uses multipart/form-data (same as channel.send). */
125
+ files?: WebhookFileData[];
126
+ /** Attachment metadata for files (id = index). Use when files are provided. */
127
+ attachments?: WebhookAttachmentMeta[];
45
128
  }
46
129
  /**
47
130
  * Represents a Discord/Fluxer webhook. Supports creating, fetching, sending, and deleting.
@@ -56,10 +139,20 @@ declare class Webhook extends Base {
56
139
  avatar: string | null;
57
140
  /** Present only when webhook was created via createWebhook(); not returned when fetching. */
58
141
  readonly token: string | null;
142
+ /** User who created the webhook. */
143
+ readonly user: User;
59
144
  /** @param data - API webhook from POST /channels/{id}/webhooks (has token) or GET /webhooks/{id} (no token) */
60
145
  constructor(client: Client, data: APIWebhook & {
61
146
  token?: string | null;
62
147
  });
148
+ /**
149
+ * Get the URL for this webhook's avatar.
150
+ * Returns null if the webhook has no custom avatar.
151
+ */
152
+ avatarURL(options?: {
153
+ size?: number;
154
+ extension?: string;
155
+ }): string | null;
63
156
  /** Delete this webhook. Requires bot token with Manage Webhooks permission. */
64
157
  delete(): Promise<void>;
65
158
  /**
@@ -70,9 +163,16 @@ declare class Webhook extends Base {
70
163
  edit(options: APIWebhookUpdateRequest | APIWebhookTokenUpdateRequest): Promise<Webhook>;
71
164
  /**
72
165
  * Send a message via this webhook. Requires the webhook token (only present when created, not when fetched).
166
+ * @param options - Text content or object with content, embeds, username, avatar_url, tts, files, attachments
167
+ * @param wait - If true, waits for the API and returns the created Message; otherwise returns void (204)
73
168
  * @throws Error if token is not available
169
+ * @example
170
+ * await webhook.send('Hello!');
171
+ * await webhook.send({ embeds: [embed.toJSON()] });
172
+ * await webhook.send({ content: 'File attached', files: [{ name: 'data.txt', data: buffer }] });
173
+ * const msg = await webhook.send({ content: 'Hi' }, true);
74
174
  */
75
- send(options: string | WebhookSendOptions): Promise<void>;
175
+ send(options: string | WebhookSendOptions, wait?: boolean): Promise<Message | undefined>;
76
176
  /**
77
177
  * Fetch a webhook by ID using bot auth.
78
178
  * @param client - The client instance
@@ -107,6 +207,12 @@ declare abstract class Channel extends Base {
107
207
  readonly client: Client;
108
208
  readonly id: string;
109
209
  type: ChannelType;
210
+ /** Channel name. Guild channels and Group DMs have names; 1:1 DMs are typically null. */
211
+ name: string | null;
212
+ /** Channel icon hash (Group DMs). Null if none. */
213
+ icon: string | null;
214
+ /** ISO timestamp when the last message was pinned. Null if never pinned. */
215
+ lastPinTimestamp: string | null;
110
216
  /** @param data - API channel from GET /channels/{id} or GET /guilds/{id}/channels */
111
217
  constructor(client: Client, data: APIChannelPartial);
112
218
  /**
@@ -120,12 +226,23 @@ declare abstract class Channel extends Base {
120
226
  * Used by ChannelManager.fetch() for GET /channels/{id}.
121
227
  */
122
228
  static fromOrCreate(client: Client, data: APIChannel | APIChannelPartial): TextChannel | DMChannel | GuildChannel | null;
229
+ /**
230
+ * Bulk delete messages. Requires Manage Messages permission.
231
+ * @param messageIds - Array of message IDs to delete (2–100)
232
+ */
233
+ bulkDeleteMessages(messageIds: string[]): Promise<void>;
234
+ /**
235
+ * Send a typing indicator to the channel. Lasts ~10 seconds.
236
+ */
237
+ sendTyping(): Promise<void>;
123
238
  }
124
239
  declare class GuildChannel extends Channel {
125
240
  readonly guildId: string;
126
241
  name: string | null;
127
242
  position?: number;
128
243
  parentId: string | null;
244
+ /** Permission overwrites for roles and members. */
245
+ permissionOverwrites: APIChannelOverwrite[];
129
246
  constructor(client: Client, data: APIChannel);
130
247
  /**
131
248
  * Create a webhook in this channel.
@@ -141,6 +258,22 @@ declare class GuildChannel extends Channel {
141
258
  * @returns Webhooks (includes token when listing from channel; can send via send())
142
259
  */
143
260
  fetchWebhooks(): Promise<Webhook[]>;
261
+ /**
262
+ * Create an invite for this channel.
263
+ * @param options - max_uses (0–100), max_age (0–604800 seconds), unique, temporary
264
+ * Requires Create Instant Invite permission.
265
+ */
266
+ createInvite(options?: {
267
+ max_uses?: number;
268
+ max_age?: number;
269
+ unique?: boolean;
270
+ temporary?: boolean;
271
+ }): Promise<Invite>;
272
+ /**
273
+ * Fetch invites for this channel.
274
+ * Requires Manage Channel permission.
275
+ */
276
+ fetchInvites(): Promise<Invite[]>;
144
277
  }
145
278
  declare class TextChannel extends GuildChannel {
146
279
  topic?: string | null;
@@ -150,14 +283,21 @@ declare class TextChannel extends GuildChannel {
150
283
  constructor(client: Client, data: APIChannel);
151
284
  /**
152
285
  * Send a message to this channel.
153
- * @param options - Text content or object with `content` and/or `embeds`
286
+ * @param options - Text content or object with content, embeds, and/or files
154
287
  */
155
- send(options: string | {
156
- content?: string;
157
- embeds?: unknown[];
158
- }): Promise<Message>;
288
+ send(options: MessageSendOptions): Promise<Message>;
159
289
  /** Message manager for this channel. Use channel.messages.fetch(messageId). */
160
290
  get messages(): MessageManager;
291
+ /**
292
+ * Create a message collector for this channel.
293
+ * Collects messages matching the filter until time expires or max is reached.
294
+ * @param options - Filter, time (ms), and max count
295
+ * @example
296
+ * const collector = channel.createMessageCollector({ filter: m => m.author.id === userId, time: 10000 });
297
+ * collector.on('collect', m => console.log(m.content));
298
+ * collector.on('end', (collected, reason) => { ... });
299
+ */
300
+ createMessageCollector(options?: MessageCollectorOptions): MessageCollector;
161
301
  /**
162
302
  * Fetch pinned messages in this channel.
163
303
  * @returns Pinned messages
@@ -169,7 +309,7 @@ declare class TextChannel extends GuildChannel {
169
309
  * @returns The message, or null if not found
170
310
  * @deprecated Use channel.messages.fetch(messageId) instead.
171
311
  */
172
- fetchMessage(messageId: string): Promise<Message | null>;
312
+ fetchMessage(messageId: string): Promise<Message>;
173
313
  }
174
314
  declare class CategoryChannel extends GuildChannel {
175
315
  }
@@ -186,17 +326,25 @@ declare class LinkChannel extends GuildChannel {
186
326
  /** DM channel (direct message between bot and a user). */
187
327
  declare class DMChannel extends Channel {
188
328
  lastMessageId?: string | null;
189
- constructor(client: Client, data: APIChannelPartial);
329
+ /** Group DM creator ID. Null for 1:1 DMs. */
330
+ ownerId: string | null;
331
+ /** Group DM recipients as User objects. Empty for 1:1 DMs. */
332
+ recipients: User[];
333
+ /** Group DM member display names (userId -> nickname). */
334
+ nicks: Record<string, string>;
335
+ constructor(client: Client, data: APIChannelPartial & Partial<APIChannel>);
190
336
  /**
191
337
  * Send a message to this DM channel.
192
- * @param options - Text content or object with `content` and/or `embeds`
338
+ * @param options - Text content or object with content, embeds, and/or files
193
339
  */
194
- send(options: string | {
195
- content?: string;
196
- embeds?: unknown[];
197
- }): Promise<Message>;
340
+ send(options: MessageSendOptions): Promise<Message>;
198
341
  /** Message manager for this channel. Use channel.messages.fetch(messageId). */
199
342
  get messages(): MessageManager;
343
+ /**
344
+ * Create a message collector for this DM channel.
345
+ * @param options - Filter, time (ms), and max count
346
+ */
347
+ createMessageCollector(options?: MessageCollectorOptions): MessageCollector;
200
348
  /**
201
349
  * Fetch pinned messages in this DM channel.
202
350
  * @returns Pinned messages
@@ -208,7 +356,68 @@ declare class DMChannel extends Channel {
208
356
  * @returns The message, or null if not found
209
357
  * @deprecated Use channel.messages.fetch(messageId) instead.
210
358
  */
211
- fetchMessage(messageId: string): Promise<Message | null>;
359
+ fetchMessage(messageId: string): Promise<Message>;
360
+ }
361
+
362
+ /** Represents a reaction added to or removed from a message. */
363
+ declare class MessageReaction extends Base {
364
+ readonly client: Client;
365
+ readonly messageId: string;
366
+ readonly channelId: string;
367
+ readonly guildId: string | null;
368
+ readonly emoji: GatewayReactionEmoji;
369
+ /** Raw gateway payload for low-level access. */
370
+ readonly _data: GatewayMessageReactionAddDispatchData | GatewayMessageReactionRemoveDispatchData;
371
+ constructor(client: Client, data: GatewayMessageReactionAddDispatchData | GatewayMessageReactionRemoveDispatchData);
372
+ /** Emoji as a string: unicode or "name:id" for custom. */
373
+ get emojiIdentifier(): string;
374
+ /** Guild where this reaction was added. Resolved from cache; null for DMs or if not cached. */
375
+ get guild(): Guild | null;
376
+ /**
377
+ * Fetch the message this reaction belongs to.
378
+ * Use when you need to edit, delete, or otherwise interact with the message.
379
+ * @throws FluxerError with MESSAGE_NOT_FOUND if the message does not exist
380
+ */
381
+ fetchMessage(): Promise<Message>;
382
+ }
383
+
384
+ interface ReactionCollectorOptions {
385
+ /** Filter function. Return true to collect the reaction. */
386
+ filter?: (reaction: MessageReaction, user: User) => boolean;
387
+ /** Max duration in ms. Collector stops when time expires. */
388
+ time?: number;
389
+ /** Max reactions to collect. Collector stops when limit reached. */
390
+ max?: number;
391
+ }
392
+ type ReactionCollectorEndReason = 'time' | 'limit' | 'user';
393
+ interface CollectedReaction {
394
+ reaction: MessageReaction;
395
+ user: User;
396
+ }
397
+ interface ReactionCollectorEvents {
398
+ collect: [reaction: MessageReaction, user: User];
399
+ end: [collected: Collection<string, CollectedReaction>, reason: ReactionCollectorEndReason];
400
+ }
401
+ /**
402
+ * Collects reactions on a message. Use message.createReactionCollector().
403
+ * @example
404
+ * const collector = message.createReactionCollector({ filter: (r, u) => u.id === userId, time: 10000 });
405
+ * collector.on('collect', (reaction, user) => console.log(user.username, 'reacted', reaction.emoji.name));
406
+ * collector.on('end', (collected, reason) => console.log(`Stopped: ${reason}`));
407
+ */
408
+ declare class ReactionCollector extends EventEmitter {
409
+ readonly client: Client;
410
+ readonly messageId: string;
411
+ readonly channelId: string;
412
+ readonly options: Required<ReactionCollectorOptions>;
413
+ readonly collected: Collection<string, CollectedReaction>;
414
+ private _timeout;
415
+ private _ended;
416
+ private _listener;
417
+ constructor(client: Client, messageId: string, channelId: string, options?: ReactionCollectorOptions);
418
+ stop(reason?: ReactionCollectorEndReason): void;
419
+ on<K extends keyof ReactionCollectorEvents>(event: K, listener: (...args: ReactionCollectorEvents[K]) => void): this;
420
+ emit<K extends keyof ReactionCollectorEvents>(event: K, ...args: ReactionCollectorEvents[K]): boolean;
212
421
  }
213
422
 
214
423
  /** Options for editing a message (content and/or embeds). */
@@ -218,6 +427,7 @@ interface MessageEditOptions {
218
427
  /** New embeds (replaces existing) */
219
428
  embeds?: (APIEmbed | EmbedBuilder)[];
220
429
  }
430
+
221
431
  /** Represents a message in a channel. */
222
432
  declare class Message extends Base {
223
433
  readonly client: Client;
@@ -241,6 +451,14 @@ declare class Message extends Base {
241
451
  readonly messageSnapshots: APIMessageSnapshot[];
242
452
  readonly call: APIMessageCall | null;
243
453
  readonly referencedMessage: Message | null;
454
+ /** Webhook ID if this message was sent via webhook. Null otherwise. */
455
+ readonly webhookId: string | null;
456
+ /** Users mentioned in this message. */
457
+ readonly mentions: User[];
458
+ /** Role IDs mentioned in this message. */
459
+ readonly mentionRoles: string[];
460
+ /** Client-side nonce for acknowledgment. Null if not provided. */
461
+ readonly nonce: string | null;
244
462
  /** Channel where this message was sent. Resolved from cache; null if not cached (e.g. DM channel not in cache). */
245
463
  get channel(): Channel | null;
246
464
  /** Guild where this message was sent. Resolved from cache; null for DMs or if not cached. */
@@ -249,15 +467,13 @@ declare class Message extends Base {
249
467
  constructor(client: Client, data: APIMessage);
250
468
  /**
251
469
  * Send a message to this channel without replying. Use when you want a standalone message.
252
- * @param options - Text content or object with content and/or embeds
470
+ * @param options - Text content or object with content, embeds, and/or files
253
471
  * @example
254
472
  * await message.send('Pong!');
255
473
  * await message.send({ embeds: [embed.toJSON()] });
474
+ * await message.send({ content: 'File', files: [{ name: 'data.txt', data }] });
256
475
  */
257
- send(options: string | {
258
- content?: string;
259
- embeds?: APIEmbed[];
260
- }): Promise<Message>;
476
+ send(options: MessageSendOptions): Promise<Message>;
261
477
  /**
262
478
  * Send a message to a specific channel. Use for logging, forwarding, or sending to another channel in the guild.
263
479
  * @param channelId - Snowflake of the target channel (e.g. log channel ID)
@@ -266,32 +482,37 @@ declare class Message extends Base {
266
482
  * await message.sendTo(logChannelId, 'User ' + message.author.username + ' said: ' + message.content);
267
483
  * await message.sendTo(announceChannelId, { embeds: [embed.toJSON()] });
268
484
  */
269
- sendTo(channelId: string, options: string | {
270
- content?: string;
271
- embeds?: APIEmbed[];
272
- }): Promise<Message>;
485
+ sendTo(channelId: string, options: MessageSendOptions): Promise<Message>;
273
486
  /**
274
487
  * Reply to this message.
275
- * @param options - Text content or object with content and/or embeds
488
+ * @param options - Text content or object with content, embeds, and/or files
276
489
  */
277
- reply(options: string | {
278
- content?: string;
279
- embeds?: APIEmbed[];
280
- }): Promise<Message>;
490
+ reply(options: MessageSendOptions): Promise<Message>;
281
491
  /**
282
492
  * Edit this message. Only the author (or admins) can edit.
283
493
  * @param options - New content and/or embeds
284
494
  */
285
495
  edit(options: MessageEditOptions): Promise<Message>;
496
+ /**
497
+ * Create a reaction collector for this message.
498
+ * Collects reactions matching the filter until time expires or max is reached.
499
+ * @param options - Filter, time (ms), and max count
500
+ * @example
501
+ * const collector = message.createReactionCollector({ filter: (r, u) => u.id === userId, time: 10000 });
502
+ * collector.on('collect', (reaction, user) => console.log(user.username, 'reacted with', reaction.emoji.name));
503
+ * collector.on('end', (collected, reason) => { ... });
504
+ */
505
+ createReactionCollector(options?: ReactionCollectorOptions): ReactionCollector;
286
506
  /**
287
507
  * Re-fetch this message from the API to get the latest content, embeds, reactions, etc.
288
508
  * Use when you have a stale Message (e.g. from an old event or cache) and need fresh data.
289
- * @returns The updated message, or null if deleted or not found
509
+ * @returns The updated message
510
+ * @throws FluxerError with MESSAGE_NOT_FOUND if the message was deleted or does not exist
290
511
  * @example
291
512
  * const updated = await message.fetch();
292
- * if (updated) console.log('Latest content:', updated.content);
513
+ * console.log('Latest content:', updated.content);
293
514
  */
294
- fetch(): Promise<Message | null>;
515
+ fetch(): Promise<Message>;
295
516
  /** Delete this message. */
296
517
  delete(): Promise<void>;
297
518
  /** Pin this message to the channel. Requires Manage Messages permission. */
@@ -337,6 +558,20 @@ declare class Message extends Base {
337
558
  id?: string;
338
559
  animated?: boolean;
339
560
  }): Promise<void>;
561
+ /**
562
+ * Fetch users who reacted with the given emoji.
563
+ * @param emoji - Unicode emoji or custom `{ name, id }`
564
+ * @param options - limit (1–100), after (user ID for pagination)
565
+ * @returns Array of User objects
566
+ */
567
+ fetchReactionUsers(emoji: string | {
568
+ name: string;
569
+ id?: string;
570
+ animated?: boolean;
571
+ }, options?: {
572
+ limit?: number;
573
+ after?: string;
574
+ }): Promise<User[]>;
340
575
  }
341
576
 
342
577
  /** Represents a user (or bot) on Fluxer. */
@@ -348,13 +583,22 @@ declare class User extends Base {
348
583
  globalName: string | null;
349
584
  avatar: string | null;
350
585
  readonly bot: boolean;
586
+ /** RGB avatar color (e.g. 7577782). Null if not set. */
587
+ avatarColor: number | null;
588
+ /** Public flags bitfield. Null if not set. */
589
+ flags: number | null;
590
+ /** Whether this is an official system user. */
591
+ readonly system: boolean;
592
+ /** Banner hash (from profile, member, or invite context). Null when not available. */
593
+ banner: string | null;
351
594
  /** @param data - API user from message author, GET /users/{id}, or GET /users/@me */
352
595
  constructor(client: Client, data: APIUserPartial);
353
596
  /** Update mutable fields from fresh API data. Used by getOrCreateUser cache. */
354
597
  _patch(data: APIUserPartial): void;
355
598
  /**
356
599
  * Get the URL for this user's avatar.
357
- * @param options - Optional `size` and `extension` (default: `png`)
600
+ * Auto-detects animated avatars (hash starting with `a_`) and uses gif extension.
601
+ * @param options - Optional `size` and `extension` (default: png, or gif for animated)
358
602
  */
359
603
  avatarURL(options?: {
360
604
  size?: number;
@@ -363,7 +607,16 @@ declare class User extends Base {
363
607
  /** Get the avatar URL, or the default avatar if none set. */
364
608
  displayAvatarURL(options?: {
365
609
  size?: number;
610
+ extension?: string;
366
611
  }): string;
612
+ /**
613
+ * Get the URL for this user's banner.
614
+ * Returns null if the user has no banner (only available when fetched from profile/member context).
615
+ */
616
+ bannerURL(options?: {
617
+ size?: number;
618
+ extension?: string;
619
+ }): string | null;
367
620
  /** Returns a mention string (e.g. `<@123456>`). */
368
621
  toString(): string;
369
622
  /**
@@ -375,10 +628,7 @@ declare class User extends Base {
375
628
  * Send a DM to this user.
376
629
  * Convenience method that creates the DM channel and sends the message.
377
630
  */
378
- send(options: string | {
379
- content?: string;
380
- embeds?: unknown[];
381
- }): Promise<Message>;
631
+ send(options: MessageSendOptions): Promise<Message>;
382
632
  }
383
633
 
384
634
  /** Represents a member of a guild. */
@@ -403,6 +653,30 @@ declare class GuildMember extends Base {
403
653
  }, guild: Guild);
404
654
  /** Nickname, or global name, or username. */
405
655
  get displayName(): string;
656
+ /**
657
+ * Get the guild-specific avatar URL for this member.
658
+ * Returns null if the member has no guild avatar (use displayAvatarURL for fallback).
659
+ */
660
+ avatarURL(options?: {
661
+ size?: number;
662
+ extension?: string;
663
+ }): string | null;
664
+ /**
665
+ * Get the avatar URL to display for this member.
666
+ * Uses guild-specific avatar if set, otherwise falls back to the user's avatar.
667
+ */
668
+ displayAvatarURL(options?: {
669
+ size?: number;
670
+ extension?: string;
671
+ }): string;
672
+ /**
673
+ * Get the guild-specific banner URL for this member.
674
+ * Returns null if the member has no guild banner.
675
+ */
676
+ bannerURL(options?: {
677
+ size?: number;
678
+ extension?: string;
679
+ }): string | null;
406
680
  /**
407
681
  * Add a role to this member.
408
682
  * @param roleId - The role ID to add
@@ -415,6 +689,30 @@ declare class GuildMember extends Base {
415
689
  * Requires Manage Roles permission.
416
690
  */
417
691
  removeRole(roleId: string): Promise<void>;
692
+ /**
693
+ * Get the member's guild-level permissions (from roles only, no channel overwrites).
694
+ * Use this for server-wide permission checks (e.g. ban, kick, manage roles).
695
+ * @returns Object with has(permission) to check specific permissions
696
+ * @example
697
+ * const perms = member.permissions;
698
+ * if (perms.has(PermissionFlags.BanMembers)) { ... }
699
+ */
700
+ get permissions(): {
701
+ has(permission: PermissionResolvable): boolean;
702
+ };
703
+ /**
704
+ * Compute the member's effective permissions in a guild channel.
705
+ * Applies role permissions and channel overwrites.
706
+ * @param channel - The guild channel to check permissions for
707
+ * @returns Object with has(permission) to check specific permissions
708
+ * @example
709
+ * const perms = member.permissionsIn(channel);
710
+ * if (perms.has(PermissionFlags.SendMessages)) { ... }
711
+ */
712
+ permissionsIn(channel: GuildChannel): {
713
+ has(permission: PermissionResolvable): boolean;
714
+ };
715
+ private _computeBasePermissions;
418
716
  }
419
717
 
420
718
  /** Represents a role in a guild. */
@@ -429,12 +727,42 @@ declare class Role extends Base {
429
727
  hoist: boolean;
430
728
  mentionable: boolean;
431
729
  unicodeEmoji: string | null;
730
+ /** Separately sorted position for hoisted roles. Null if not set. */
731
+ hoistPosition: number | null;
432
732
  /** @param client - The client instance */
433
733
  /** @param data - API role from GET /guilds/{id}/roles or gateway role events */
434
734
  /** @param guildId - The guild this role belongs to */
435
735
  constructor(client: Client, data: APIRole, guildId: string);
436
736
  /** Returns a mention string (e.g. `<@&123456>`). */
437
737
  toString(): string;
738
+ /**
739
+ * Check if this role has a permission. Administrator grants all permissions.
740
+ * @param permission - Permission flag, name, or resolvable
741
+ * @returns true if the role has the permission
742
+ * @example
743
+ * if (role.has(PermissionFlags.BanMembers)) { ... }
744
+ * if (role.has('ManageChannels')) { ... }
745
+ */
746
+ has(permission: PermissionResolvable): boolean;
747
+ }
748
+
749
+ /** Represents a ban in a guild. */
750
+ declare class GuildBan extends Base {
751
+ readonly client: Client;
752
+ readonly guildId: string;
753
+ readonly user: User;
754
+ readonly reason: string | null;
755
+ /** ISO timestamp when a temporary ban expires. Null for permanent bans. */
756
+ readonly expiresAt: string | null;
757
+ /** @param data - API ban from GET /guilds/{id}/bans or gateway GUILD_BAN_ADD */
758
+ constructor(client: Client, data: APIBan & {
759
+ guild_id?: string;
760
+ }, guildId: string);
761
+ /**
762
+ * Remove this ban (unban the user).
763
+ * Requires Ban Members permission.
764
+ */
765
+ unban(): Promise<void>;
438
766
  }
439
767
 
440
768
  /** Represents a Fluxer guild (server). */
@@ -445,12 +773,40 @@ declare class Guild extends Base {
445
773
  icon: string | null;
446
774
  banner: string | null;
447
775
  readonly ownerId: string;
776
+ /** Invite splash image hash. Null if none. */
777
+ splash: string | null;
778
+ /** Custom vanity URL code (e.g. fluxer.gg/code). Null if none. */
779
+ vanityURLCode: string | null;
780
+ /** Enabled guild features. */
781
+ features: GuildFeature[];
782
+ verificationLevel: GuildVerificationLevel;
783
+ defaultMessageNotifications: DefaultMessageNotifications;
784
+ explicitContentFilter: GuildExplicitContentFilter;
785
+ /** AFK voice channel ID. Null if none. */
786
+ afkChannelId: string | null;
787
+ /** AFK timeout in seconds. */
788
+ afkTimeout: number;
789
+ /** System messages channel ID. Null if none. */
790
+ systemChannelId: string | null;
791
+ /** Rules/guidelines channel ID. Null if none. */
792
+ rulesChannelId: string | null;
793
+ nsfwLevel: number;
794
+ mfaLevel: GuildMFALevel;
795
+ /** Banner image width. Optional. */
796
+ bannerWidth?: number | null;
797
+ /** Banner image height. Optional. */
798
+ bannerHeight?: number | null;
799
+ /** Splash image width. Optional. */
800
+ splashWidth?: number | null;
801
+ /** Splash image height. Optional. */
802
+ splashHeight?: number | null;
448
803
  members: Collection<string, GuildMember>;
449
804
  channels: Collection<string, GuildChannel>;
450
805
  roles: Collection<string, Role>;
451
806
  /** @param data - API guild from GET /guilds/{id} or gateway GUILD_CREATE */
452
807
  constructor(client: Client, data: APIGuild & {
453
808
  roles?: APIRole[];
809
+ ownerId?: string;
454
810
  });
455
811
  /** Get the guild icon URL, or null if no icon. */
456
812
  iconURL(options?: {
@@ -460,6 +816,10 @@ declare class Guild extends Base {
460
816
  bannerURL(options?: {
461
817
  size?: number;
462
818
  }): string | null;
819
+ /** Get the guild splash (invite background) URL, or null if no splash. */
820
+ splashURL(options?: {
821
+ size?: number;
822
+ }): string | null;
463
823
  /**
464
824
  * Add a role to a member by user ID. Does not require fetching the member first.
465
825
  * @param userId - The user ID of the member
@@ -481,12 +841,43 @@ declare class Guild extends Base {
481
841
  * @returns The role ID, or null if not found
482
842
  */
483
843
  resolveRoleId(arg: string): Promise<string | null>;
844
+ /**
845
+ * Ban a user from this guild.
846
+ * @param userId - The user ID to ban
847
+ * @param options - Optional reason, delete_message_days (0–7), and ban_duration_seconds (temporary ban).
848
+ * ban_duration_seconds: 0 = permanent, or use 3600, 43200, 86400, 259200, 432000, 604800, 1209600, 2592000.
849
+ * Requires Ban Members permission.
850
+ */
851
+ ban(userId: string, options?: {
852
+ reason?: string;
853
+ delete_message_days?: number;
854
+ ban_duration_seconds?: number;
855
+ }): Promise<void>;
856
+ /**
857
+ * Fetch guild bans. Requires Ban Members permission.
858
+ * @returns List of GuildBan objects
859
+ */
860
+ fetchBans(): Promise<GuildBan[]>;
861
+ /**
862
+ * Remove a ban (unban a user).
863
+ * @param userId - The user ID to unban
864
+ * Requires Ban Members permission.
865
+ */
866
+ unban(userId: string): Promise<void>;
867
+ /**
868
+ * Kick a member from this guild.
869
+ * @param userId - The user ID to kick
870
+ * Requires Kick Members permission.
871
+ */
872
+ kick(userId: string): Promise<void>;
484
873
  /**
485
874
  * Fetch a guild member by user ID.
486
875
  * @param userId - The user ID of the member to fetch
487
- * @returns The guild member, or null if not found
876
+ * @returns The guild member
877
+ * @throws FluxerError with MEMBER_NOT_FOUND if user is not in the guild (404)
878
+ * @throws FluxerError with cause for permission denied (403) or other REST errors
488
879
  */
489
- fetchMember(userId: string): Promise<GuildMember | null>;
880
+ fetchMember(userId: string): Promise<GuildMember>;
490
881
  /**
491
882
  * Fetch guild audit logs. Requires View Audit Log permission.
492
883
  * @param options - Optional limit, before, after, user_id, action_type for filtering
@@ -500,6 +891,42 @@ declare class Guild extends Base {
500
891
  }): Promise<APIGuildAuditLog>;
501
892
  /** Fetch all webhooks in this guild. Returned webhooks do not include the token (cannot send). */
502
893
  fetchWebhooks(): Promise<Webhook[]>;
894
+ /**
895
+ * Create a channel in this guild.
896
+ * @param data - Channel data: type (0=text, 2=voice, 4=category, 5=link), name, and optional parent_id, topic, bitrate, user_limit, nsfw, permission_overwrites
897
+ * Requires Manage Channels permission.
898
+ */
899
+ createChannel(data: {
900
+ type: 0 | 2 | 4 | 5;
901
+ name: string;
902
+ parent_id?: string | null;
903
+ topic?: string | null;
904
+ bitrate?: number | null;
905
+ user_limit?: number | null;
906
+ nsfw?: boolean;
907
+ permission_overwrites?: Array<{
908
+ id: string;
909
+ type: number;
910
+ allow: string;
911
+ deny: string;
912
+ }>;
913
+ }): Promise<GuildChannel>;
914
+ /**
915
+ * Fetch all channels in this guild.
916
+ * @returns Array of GuildChannel objects (cached in guild.channels and client.channels)
917
+ */
918
+ fetchChannels(): Promise<GuildChannel[]>;
919
+ /**
920
+ * Update channel positions.
921
+ * @param updates - Array of { id, position?, parent_id?, lock_permissions? }
922
+ * Requires Manage Channels permission.
923
+ */
924
+ setChannelPositions(updates: Array<{
925
+ id: string;
926
+ position?: number;
927
+ parent_id?: string | null;
928
+ lock_permissions?: boolean;
929
+ }>): Promise<void>;
503
930
  }
504
931
 
505
932
  /** Represents an invite to a guild or channel. */
@@ -534,44 +961,6 @@ declare class Invite extends Base {
534
961
  delete(): Promise<void>;
535
962
  }
536
963
 
537
- /** Represents a ban in a guild. */
538
- declare class GuildBan extends Base {
539
- readonly client: Client;
540
- readonly guildId: string;
541
- readonly user: User;
542
- readonly reason: string | null;
543
- /** @param data - API ban from GET /guilds/{id}/bans or gateway GUILD_BAN_ADD */
544
- constructor(client: Client, data: APIBan & {
545
- guild_id?: string;
546
- }, guildId: string);
547
- /**
548
- * Remove this ban (unban the user).
549
- * Requires Ban Members permission.
550
- */
551
- unban(): Promise<void>;
552
- }
553
-
554
- /** Represents a reaction added to or removed from a message. */
555
- declare class MessageReaction extends Base {
556
- readonly client: Client;
557
- readonly messageId: string;
558
- readonly channelId: string;
559
- readonly guildId: string | null;
560
- readonly emoji: GatewayReactionEmoji;
561
- /** Raw gateway payload for low-level access. */
562
- readonly _data: GatewayMessageReactionAddDispatchData | GatewayMessageReactionRemoveDispatchData;
563
- constructor(client: Client, data: GatewayMessageReactionAddDispatchData | GatewayMessageReactionRemoveDispatchData);
564
- /** Emoji as a string: unicode or "name:id" for custom. */
565
- get emojiIdentifier(): string;
566
- /** Guild where this reaction was added. Resolved from cache; null for DMs or if not cached. */
567
- get guild(): Guild | null;
568
- /**
569
- * Fetch the message this reaction belongs to.
570
- * Use when you need to edit, delete, or otherwise interact with the message.
571
- */
572
- fetchMessage(): Promise<Message | null>;
573
- }
574
-
575
964
  /** Minimal message data for MessageDelete when the full message is not available. */
576
965
  interface PartialMessage {
577
966
  id: string;
@@ -589,37 +978,37 @@ declare class ChannelManager extends Collection<string, Channel> {
589
978
  /**
590
979
  * Fetch a channel by ID from the API (or return from cache if present).
591
980
  * @param channelId - Snowflake of the channel
592
- * @returns The channel, or null if not found
981
+ * @returns The channel
982
+ * @throws FluxerError with CHANNEL_NOT_FOUND if the channel does not exist
593
983
  * @example
594
984
  * const channel = await client.channels.fetch(channelId);
595
985
  * if (channel?.isSendable()) await channel.send('Hello!');
596
986
  */
597
- fetch(channelId: string): Promise<Channel | null>;
987
+ fetch(channelId: string): Promise<Channel>;
598
988
  /**
599
989
  * Fetch a message by ID from the API.
600
990
  * @param channelId - Snowflake of the channel
601
991
  * @param messageId - Snowflake of the message
602
- * @returns The message, or null if not found
992
+ * @returns The message
993
+ * @throws FluxerError with MESSAGE_NOT_FOUND if the message does not exist
603
994
  * @deprecated Use channel.messages.fetch(messageId). Prefer (await client.channels.fetch(channelId))?.messages?.fetch(messageId).
604
995
  * @example
605
996
  * const channel = await client.channels.fetch(channelId);
606
997
  * const message = await channel?.messages?.fetch(messageId);
607
998
  */
608
- fetchMessage(channelId: string, messageId: string): Promise<Message | null>;
999
+ fetchMessage(channelId: string, messageId: string): Promise<Message>;
609
1000
  /**
610
1001
  * Send a message to a channel by ID. Works even when the channel is not cached.
611
1002
  * Skips the fetch when you only need to send.
612
1003
  * @param channelId - Snowflake of the channel (text channel or DM)
613
- * @param payload - Text content or object with content and/or embeds
1004
+ * @param payload - Text content or object with content, embeds, and/or files
614
1005
  * @returns The created message
615
1006
  * @example
616
1007
  * await client.channels.send(logChannelId, 'User joined!');
617
1008
  * await client.channels.send(channelId, { embeds: [embed.toJSON()] });
1009
+ * await client.channels.send(channelId, { content: 'Report', files: [{ name: 'log.txt', data }] });
618
1010
  */
619
- send(channelId: string, payload: string | {
620
- content?: string;
621
- embeds?: _fluxerjs_types.APIEmbed[];
622
- }): Promise<Message>;
1011
+ send(channelId: string, payload: MessageSendOptions): Promise<Message>;
623
1012
  }
624
1013
 
625
1014
  /**
@@ -658,8 +1047,19 @@ interface ClientOptions {
658
1047
  declare class ClientUser extends User {
659
1048
  readonly client: Client;
660
1049
  constructor(client: Client, data: APIUserPartial);
1050
+ /**
1051
+ * Fetch guilds the bot is a member of.
1052
+ * @returns Array of Guild objects (cached in client.guilds)
1053
+ */
1054
+ fetchGuilds(): Promise<Guild[]>;
1055
+ /**
1056
+ * Leave a guild. Requires the bot to be a member.
1057
+ * @param guildId - The guild ID to leave
1058
+ */
1059
+ leaveGuild(guildId: string): Promise<void>;
661
1060
  }
662
1061
 
1062
+ /** Event name constants for client.on(Events.X, handler). Use with ClientEvents for typed callbacks. */
663
1063
  declare const Events: {
664
1064
  readonly Ready: "ready";
665
1065
  readonly MessageCreate: "messageCreate";
@@ -706,6 +1106,10 @@ declare const Events: {
706
1106
  readonly Debug: "debug";
707
1107
  };
708
1108
 
1109
+ /**
1110
+ * Callback parameter types for client events. Use with client.on(Events.X, handler).
1111
+ * @see Events
1112
+ */
709
1113
  interface ClientEvents {
710
1114
  [Events.Ready]: [];
711
1115
  [Events.MessageCreate]: [message: Message];
@@ -716,11 +1120,19 @@ interface ClientEvents {
716
1120
  [Events.MessageDelete]: [message: PartialMessage];
717
1121
  [Events.MessageReactionAdd]: [
718
1122
  reaction: MessageReaction,
719
- user: User
1123
+ user: User,
1124
+ messageId: string,
1125
+ channelId: string,
1126
+ emoji: GatewayReactionEmoji,
1127
+ userId: string
720
1128
  ];
721
1129
  [Events.MessageReactionRemove]: [
722
1130
  reaction: MessageReaction,
723
- user: User
1131
+ user: User,
1132
+ messageId: string,
1133
+ channelId: string,
1134
+ emoji: GatewayReactionEmoji,
1135
+ userId: string
724
1136
  ];
725
1137
  [Events.MessageReactionRemoveAll]: [data: GatewayMessageReactionRemoveAllDispatchData];
726
1138
  [Events.MessageReactionRemoveEmoji]: [data: GatewayMessageReactionRemoveEmojiDispatchData];
@@ -755,28 +1167,30 @@ interface ClientEvents {
755
1167
  ];
756
1168
  [Events.GuildBanAdd]: [ban: GuildBan];
757
1169
  [Events.GuildBanRemove]: [ban: GuildBan];
758
- [Events.GuildEmojisUpdate]: [data: unknown];
759
- [Events.GuildStickersUpdate]: [data: unknown];
760
- [Events.GuildIntegrationsUpdate]: [data: unknown];
1170
+ [Events.GuildEmojisUpdate]: [data: GatewayGuildEmojisUpdateDispatchData];
1171
+ [Events.GuildStickersUpdate]: [data: GatewayGuildStickersUpdateDispatchData];
1172
+ [Events.GuildIntegrationsUpdate]: [data: GatewayGuildIntegrationsUpdateDispatchData];
761
1173
  [Events.GuildRoleCreate]: [data: _fluxerjs_types.GatewayGuildRoleCreateDispatchData];
762
1174
  [Events.GuildRoleUpdate]: [data: _fluxerjs_types.GatewayGuildRoleUpdateDispatchData];
763
1175
  [Events.GuildRoleDelete]: [data: _fluxerjs_types.GatewayGuildRoleDeleteDispatchData];
764
- [Events.GuildScheduledEventCreate]: [data: unknown];
765
- [Events.GuildScheduledEventUpdate]: [data: unknown];
766
- [Events.GuildScheduledEventDelete]: [data: unknown];
767
- [Events.ChannelPinsUpdate]: [data: unknown];
1176
+ [Events.GuildScheduledEventCreate]: [data: GatewayGuildScheduledEventCreateDispatchData];
1177
+ [Events.GuildScheduledEventUpdate]: [data: GatewayGuildScheduledEventUpdateDispatchData];
1178
+ [Events.GuildScheduledEventDelete]: [data: GatewayGuildScheduledEventDeleteDispatchData];
1179
+ [Events.ChannelPinsUpdate]: [data: GatewayChannelPinsUpdateDispatchData];
768
1180
  [Events.InviteCreate]: [invite: Invite];
769
- [Events.InviteDelete]: [
770
- data: _fluxerjs_types.GatewayInviteDeleteDispatchData
771
- ];
1181
+ [Events.InviteDelete]: [data: _fluxerjs_types.GatewayInviteDeleteDispatchData];
772
1182
  [Events.TypingStart]: [data: _fluxerjs_types.GatewayTypingStartDispatchData];
773
1183
  [Events.UserUpdate]: [data: _fluxerjs_types.GatewayUserUpdateDispatchData];
774
- [Events.PresenceUpdate]: [data: unknown];
775
- [Events.WebhooksUpdate]: [data: unknown];
1184
+ [Events.PresenceUpdate]: [data: GatewayPresenceUpdateDispatchData];
1185
+ [Events.WebhooksUpdate]: [data: GatewayWebhooksUpdateDispatchData];
776
1186
  [Events.Resumed]: [];
777
1187
  [Events.Error]: [error: Error];
778
1188
  [Events.Debug]: [message: string];
779
1189
  }
1190
+ /** Typed event handler methods. Use client.events.MessageReactionAdd((reaction, user, messageId, channelId, emoji, userId) => {...}) or client.on(Events.MessageReactionAdd, ...). */
1191
+ type ClientEventMethods = {
1192
+ [K in keyof typeof Events]: (cb: (...args: ClientEvents[(typeof Events)[K]]) => void) => Client;
1193
+ };
780
1194
  /** Main Fluxer bot client. Connects to the gateway, emits events, and provides REST access. */
781
1195
  declare class Client extends EventEmitter {
782
1196
  readonly options: ClientOptions;
@@ -784,7 +1198,11 @@ declare class Client extends EventEmitter {
784
1198
  readonly guilds: GuildManager;
785
1199
  readonly channels: ChannelManager;
786
1200
  readonly users: Collection<string, User>;
1201
+ /** Typed event handlers. Use client.events.MessageReactionAdd((reaction, user, messageId, channelId, emoji, userId) => {...}) or client.on(Events.MessageReactionAdd, ...). */
1202
+ readonly events: ClientEventMethods;
1203
+ /** The authenticated bot user. Null until READY is received. */
787
1204
  user: ClientUser | null;
1205
+ /** Timestamp when the client became ready. Null until READY is received. */
788
1206
  readyAt: Date | null;
789
1207
  private _ws;
790
1208
  /** @param options - Token, REST config, WebSocket, presence, etc. */
@@ -806,13 +1224,14 @@ declare class Client extends EventEmitter {
806
1224
  * Fetch a message by channel and message ID. Use when you have IDs (e.g. from a DB).
807
1225
  * @param channelId - Snowflake of the channel
808
1226
  * @param messageId - Snowflake of the message
809
- * @returns The message, or null if not found
1227
+ * @returns The message
1228
+ * @throws FluxerError with MESSAGE_NOT_FOUND if the message does not exist
810
1229
  * @deprecated Use channel.messages.fetch(messageId). For IDs-only: (await client.channels.fetch(channelId))?.messages?.fetch(messageId)
811
1230
  * @example
812
1231
  * const channel = await client.channels.fetch(channelId);
813
1232
  * const message = await channel?.messages?.fetch(messageId);
814
1233
  */
815
- fetchMessage(channelId: string, messageId: string): Promise<Message | null>;
1234
+ fetchMessage(channelId: string, messageId: string): Promise<Message>;
816
1235
  /**
817
1236
  * Send a message to any channel by ID. Shorthand for client.channels.send().
818
1237
  * Works even when the channel is not cached.
@@ -902,13 +1321,84 @@ declare class GuildSticker extends Base {
902
1321
  }): Promise<GuildSticker>;
903
1322
  }
904
1323
 
1324
+ interface FluxerErrorOptions {
1325
+ code?: string;
1326
+ cause?: Error;
1327
+ }
905
1328
  declare class FluxerError extends Error {
906
- constructor(message: string);
1329
+ readonly code?: string;
1330
+ constructor(message: string, options?: FluxerErrorOptions);
907
1331
  }
908
1332
 
909
1333
  declare const ErrorCodes: {
910
1334
  readonly ClientNotReady: "CLIENT_NOT_READY";
911
1335
  readonly InvalidToken: "INVALID_TOKEN";
1336
+ readonly AlreadyLoggedIn: "ALREADY_LOGGED_IN";
1337
+ readonly ChannelNotFound: "CHANNEL_NOT_FOUND";
1338
+ readonly MessageNotFound: "MESSAGE_NOT_FOUND";
1339
+ readonly GuildNotFound: "GUILD_NOT_FOUND";
1340
+ readonly MemberNotFound: "MEMBER_NOT_FOUND";
912
1341
  };
913
1342
 
914
- export { Base, CategoryChannel, Channel, ChannelManager, Client, type ClientEvents, ClientUser, DMChannel, ErrorCodes, Events, FluxerError, Guild, GuildBan, GuildChannel, GuildEmoji, GuildMember, GuildSticker, Invite, LinkChannel, Message, type MessageEditOptions, MessageManager, MessageReaction, type PartialMessage, Role, TextChannel, User, VoiceChannel, Webhook, type WebhookSendOptions };
1343
+ interface CdnUrlOptions {
1344
+ size?: number;
1345
+ extension?: string;
1346
+ }
1347
+ /**
1348
+ * Build a user avatar URL from raw API data.
1349
+ * @param userId - The user's snowflake ID
1350
+ * @param avatarHash - The avatar hash from the API, or null if no custom avatar
1351
+ * @param options - Optional size and extension (default: png; auto-detects gif for a_ hashes)
1352
+ * @returns The avatar URL, or null if no avatar hash
1353
+ * @example
1354
+ * const url = cdnAvatarURL(userData.id, userData.avatar, { size: 256 });
1355
+ */
1356
+ declare function cdnAvatarURL(userId: string, avatarHash: string | null, options?: CdnUrlOptions): string | null;
1357
+ /**
1358
+ * Build an avatar URL, or the default avatar when none set.
1359
+ * @param userId - The user's snowflake ID
1360
+ * @param avatarHash - The avatar hash from the API, or null
1361
+ * @param options - Optional size and extension
1362
+ * @returns The avatar URL (never null)
1363
+ * @example
1364
+ * const url = cdnDisplayAvatarURL(user.id, user.avatar, { size: 64 });
1365
+ */
1366
+ declare function cdnDisplayAvatarURL(userId: string, avatarHash: string | null, options?: CdnUrlOptions): string;
1367
+ /**
1368
+ * Build a user or guild banner URL from raw API data.
1369
+ * @param resourceId - The user ID or guild ID
1370
+ * @param bannerHash - The banner hash from the API, or null
1371
+ * @param options - Optional size and extension (default: png; auto-detects gif for a_ hashes)
1372
+ * @returns The banner URL, or null if no banner
1373
+ * @example
1374
+ * const url = cdnBannerURL(userData.id, profile.banner, { size: 512 });
1375
+ */
1376
+ declare function cdnBannerURL(resourceId: string, bannerHash: string | null, options?: CdnUrlOptions): string | null;
1377
+ /**
1378
+ * Build a guild member avatar URL (guild-specific avatar).
1379
+ * @param guildId - The guild ID
1380
+ * @param userId - The user ID
1381
+ * @param avatarHash - The member avatar hash, or null
1382
+ * @param options - Optional size and extension
1383
+ * @returns The member avatar URL, or null if no guild avatar
1384
+ * @example
1385
+ * const url = cdnMemberAvatarURL(member.guild.id, member.id, member.avatar);
1386
+ */
1387
+ declare function cdnMemberAvatarURL(guildId: string, userId: string, avatarHash: string | null, options?: CdnUrlOptions): string | null;
1388
+ /**
1389
+ * Build a guild member banner URL (guild-specific banner).
1390
+ * @param guildId - The guild ID
1391
+ * @param userId - The user ID
1392
+ * @param bannerHash - The member banner hash, or null
1393
+ * @param options - Optional size and extension
1394
+ * @returns The member banner URL, or null if no guild banner
1395
+ */
1396
+ declare function cdnMemberBannerURL(guildId: string, userId: string, bannerHash: string | null, options?: CdnUrlOptions): string | null;
1397
+ /**
1398
+ * Get the default avatar URL (used when user has no custom avatar).
1399
+ * @param discriminatorIndex - Optional index 0-4 for default avatar variant
1400
+ * @returns The default avatar URL
1401
+ */
1402
+ declare function cdnDefaultAvatarURL(discriminatorIndex?: number): string;
1403
+
1404
+ export { Base, CategoryChannel, type CdnUrlOptions, Channel, ChannelManager, Client, type ClientEventMethods, type ClientEvents, ClientUser, type CollectedReaction, DMChannel, ErrorCodes, Events, FluxerError, type FluxerErrorOptions, Guild, GuildBan, GuildChannel, GuildEmoji, GuildMember, GuildSticker, Invite, LinkChannel, Message, MessageCollector, type MessageCollectorEndReason, type MessageCollectorOptions, type MessageEditOptions, MessageManager, MessageReaction, type MessageSendOptions, type PartialMessage, ReactionCollector, type ReactionCollectorEndReason, type ReactionCollectorOptions, Role, TextChannel, User, VoiceChannel, Webhook, type WebhookSendOptions, cdnAvatarURL, cdnBannerURL, cdnDefaultAvatarURL, cdnDisplayAvatarURL, cdnMemberAvatarURL, cdnMemberBannerURL };