@fluxerjs/core 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/{Channel-TWPDKW2P.mjs → Channel-WJZZSNML.mjs} +3 -1
  2. package/dist/{ClientUser-2K2BACK7.mjs → ClientUser-DJO2FS7P.mjs} +1 -1
  3. package/dist/Guild-2P77HBQM.mjs +11 -0
  4. package/dist/GuildBan-7CXLTPKY.mjs +7 -0
  5. package/dist/GuildMember-43B5E5CH.mjs +9 -0
  6. package/dist/{Message-G2QIKZQK.mjs → Invite-UM5BU5A6.mjs} +3 -3
  7. package/dist/Message-OFIVTTAZ.mjs +9 -0
  8. package/dist/{MessageReaction-XRPYZDSC.mjs → MessageReaction-V4UZ7OXE.mjs} +1 -1
  9. package/dist/{Role-SVLWIAMN.mjs → Role-5MWSGL66.mjs} +1 -1
  10. package/dist/Webhook-RWDDYW2Q.mjs +10 -0
  11. package/dist/chunk-4XJIM6SC.mjs +315 -0
  12. package/dist/chunk-AH7KYH2Z.mjs +50 -0
  13. package/dist/{chunk-HBF5QEDH.mjs → chunk-CEABHTAF.mjs} +1 -0
  14. package/dist/chunk-CJVQNARM.mjs +145 -0
  15. package/dist/chunk-DQ4TNBPG.mjs +63 -0
  16. package/dist/chunk-DUQAD7F6.mjs +173 -0
  17. package/dist/{chunk-4GCZFOS5.mjs → chunk-JHNKZIHY.mjs} +54 -3
  18. package/dist/chunk-LU2SNC5G.mjs +392 -0
  19. package/dist/chunk-PM2IUGNR.mjs +29 -0
  20. package/dist/chunk-QEXIYXXU.mjs +62 -0
  21. package/dist/chunk-UXIF75BV.mjs +36 -0
  22. package/dist/chunk-V7LPVPGH.mjs +305 -0
  23. package/dist/chunk-X6K3ZD62.mjs +53 -0
  24. package/dist/index.d.mts +802 -160
  25. package/dist/index.d.ts +802 -160
  26. package/dist/index.js +1467 -262
  27. package/dist/index.mjs +292 -119
  28. package/package.json +7 -7
  29. package/dist/Guild-CMZGA6DW.mjs +0 -10
  30. package/dist/GuildMember-DW2N6ITI.mjs +0 -7
  31. package/dist/Webhook-2MQESB7Z.mjs +0 -7
  32. package/dist/chunk-CO5EL5LH.mjs +0 -168
  33. package/dist/chunk-CZIO2D7F.mjs +0 -207
  34. package/dist/chunk-JVEOQFUX.mjs +0 -52
  35. package/dist/chunk-SQVCCSNN.mjs +0 -41
  36. package/dist/chunk-TJVZEILY.mjs +0 -120
  37. package/dist/chunk-ZGMM6IPQ.mjs +0 -79
package/dist/index.d.ts CHANGED
@@ -1,14 +1,18 @@
1
- import { Collection } from '@fluxerjs/collection';
2
1
  import * as _fluxerjs_types from '@fluxerjs/types';
3
- import { APIWebhook, APIChannel, APIChannelPartial, ChannelType, APIRole, APIGuild, APIMessageAttachment, APIMessage, APIEmbed, APIUserPartial, APIGuildMember, GatewayReactionEmoji, GatewayMessageReactionAddDispatchData, GatewayMessageReactionRemoveDispatchData, GatewayPresenceUpdateData, GatewaySendPayload, Routes, GatewayMessageReactionRemoveAllDispatchData, GatewayMessageReactionRemoveEmojiDispatchData, GatewayVoiceStateUpdateDispatchData, GatewayVoiceServerUpdateDispatchData } from '@fluxerjs/types';
4
- 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
+ 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.
@@ -51,22 +134,45 @@ declare class Webhook extends Base {
51
134
  readonly client: Client;
52
135
  readonly id: string;
53
136
  readonly guildId: string;
54
- readonly channelId: string;
137
+ channelId: string;
55
138
  name: string;
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>;
158
+ /**
159
+ * Edit this webhook. With token: name and avatar only. Without token (bot auth): name, avatar, and channel_id.
160
+ * @param options - Fields to update (name, avatar, channel_id when using bot auth)
161
+ * @returns This webhook instance with updated fields
162
+ */
163
+ edit(options: APIWebhookUpdateRequest | APIWebhookTokenUpdateRequest): Promise<Webhook>;
65
164
  /**
66
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)
67
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);
68
174
  */
69
- send(options: string | WebhookSendOptions): Promise<void>;
175
+ send(options: string | WebhookSendOptions, wait?: boolean): Promise<Message | undefined>;
70
176
  /**
71
177
  * Fetch a webhook by ID using bot auth.
72
178
  * @param client - The client instance
@@ -101,6 +207,12 @@ declare abstract class Channel extends Base {
101
207
  readonly client: Client;
102
208
  readonly id: string;
103
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;
104
216
  /** @param data - API channel from GET /channels/{id} or GET /guilds/{id}/channels */
105
217
  constructor(client: Client, data: APIChannelPartial);
106
218
  /**
@@ -114,12 +226,23 @@ declare abstract class Channel extends Base {
114
226
  * Used by ChannelManager.fetch() for GET /channels/{id}.
115
227
  */
116
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>;
117
238
  }
118
239
  declare class GuildChannel extends Channel {
119
240
  readonly guildId: string;
120
241
  name: string | null;
121
242
  position?: number;
122
243
  parentId: string | null;
244
+ /** Permission overwrites for roles and members. */
245
+ permissionOverwrites: APIChannelOverwrite[];
123
246
  constructor(client: Client, data: APIChannel);
124
247
  /**
125
248
  * Create a webhook in this channel.
@@ -135,6 +258,22 @@ declare class GuildChannel extends Channel {
135
258
  * @returns Webhooks (includes token when listing from channel; can send via send())
136
259
  */
137
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[]>;
138
277
  }
139
278
  declare class TextChannel extends GuildChannel {
140
279
  topic?: string | null;
@@ -144,21 +283,33 @@ declare class TextChannel extends GuildChannel {
144
283
  constructor(client: Client, data: APIChannel);
145
284
  /**
146
285
  * Send a message to this channel.
147
- * @param options - Text content or object with `content` and/or `embeds`
286
+ * @param options - Text content or object with content, embeds, and/or files
148
287
  */
149
- send(options: string | {
150
- content?: string;
151
- embeds?: unknown[];
152
- }): Promise<Message>;
288
+ send(options: MessageSendOptions): Promise<Message>;
153
289
  /** Message manager for this channel. Use channel.messages.fetch(messageId). */
154
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;
301
+ /**
302
+ * Fetch pinned messages in this channel.
303
+ * @returns Pinned messages
304
+ */
305
+ fetchPinnedMessages(): Promise<Message[]>;
155
306
  /**
156
307
  * Fetch a message by ID from this channel.
157
308
  * @param messageId - Snowflake of the message
158
309
  * @returns The message, or null if not found
159
310
  * @deprecated Use channel.messages.fetch(messageId) instead.
160
311
  */
161
- fetchMessage(messageId: string): Promise<Message | null>;
312
+ fetchMessage(messageId: string): Promise<Message>;
162
313
  }
163
314
  declare class CategoryChannel extends GuildChannel {
164
315
  }
@@ -175,98 +326,98 @@ declare class LinkChannel extends GuildChannel {
175
326
  /** DM channel (direct message between bot and a user). */
176
327
  declare class DMChannel extends Channel {
177
328
  lastMessageId?: string | null;
178
- 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>);
179
336
  /**
180
337
  * Send a message to this DM channel.
181
- * @param options - Text content or object with `content` and/or `embeds`
338
+ * @param options - Text content or object with content, embeds, and/or files
182
339
  */
183
- send(options: string | {
184
- content?: string;
185
- embeds?: unknown[];
186
- }): Promise<Message>;
340
+ send(options: MessageSendOptions): Promise<Message>;
187
341
  /** Message manager for this channel. Use channel.messages.fetch(messageId). */
188
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;
348
+ /**
349
+ * Fetch pinned messages in this DM channel.
350
+ * @returns Pinned messages
351
+ */
352
+ fetchPinnedMessages(): Promise<Message[]>;
189
353
  /**
190
354
  * Fetch a message by ID from this DM channel.
191
355
  * @param messageId - Snowflake of the message
192
356
  * @returns The message, or null if not found
193
357
  * @deprecated Use channel.messages.fetch(messageId) instead.
194
358
  */
195
- fetchMessage(messageId: string): Promise<Message | null>;
359
+ fetchMessage(messageId: string): Promise<Message>;
196
360
  }
197
361
 
198
- /** Represents a role in a guild. */
199
- declare class Role extends Base {
362
+ /** Represents a reaction added to or removed from a message. */
363
+ declare class MessageReaction extends Base {
200
364
  readonly client: Client;
201
- readonly id: string;
202
- readonly guildId: string;
203
- name: string;
204
- color: number;
205
- position: number;
206
- permissions: string;
207
- hoist: boolean;
208
- mentionable: boolean;
209
- unicodeEmoji: string | null;
210
- /** @param client - The client instance */
211
- /** @param data - API role from GET /guilds/{id}/roles or gateway role events */
212
- /** @param guildId - The guild this role belongs to */
213
- constructor(client: Client, data: APIRole, guildId: string);
214
- /** Returns a mention string (e.g. `<@&123456>`). */
215
- toString(): string;
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>;
216
382
  }
217
383
 
218
- /** Represents a Fluxer guild (server). */
219
- declare class Guild extends Base {
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 {
220
409
  readonly client: Client;
221
- readonly id: string;
222
- name: string;
223
- icon: string | null;
224
- banner: string | null;
225
- readonly ownerId: string;
226
- members: Collection<string, GuildMember>;
227
- channels: Collection<string, GuildChannel>;
228
- roles: Collection<string, Role>;
229
- /** @param data - API guild from GET /guilds/{id} or gateway GUILD_CREATE */
230
- constructor(client: Client, data: APIGuild & {
231
- roles?: APIRole[];
232
- });
233
- /** Get the guild icon URL, or null if no icon. */
234
- iconURL(options?: {
235
- size?: number;
236
- }): string | null;
237
- /** Get the guild banner URL, or null if no banner. */
238
- bannerURL(options?: {
239
- size?: number;
240
- }): string | null;
241
- /**
242
- * Add a role to a member by user ID. Does not require fetching the member first.
243
- * @param userId - The user ID of the member
244
- * @param roleId - The role ID to add (or use guild.resolveRoleId for mention/name resolution)
245
- * Requires Manage Roles permission.
246
- */
247
- addRoleToMember(userId: string, roleId: string): Promise<void>;
248
- /**
249
- * Remove a role from a member by user ID. Does not require fetching the member first.
250
- * @param userId - The user ID of the member
251
- * @param roleId - The role ID to remove
252
- * Requires Manage Roles permission.
253
- */
254
- removeRoleFromMember(userId: string, roleId: string): Promise<void>;
255
- /**
256
- * Resolve a role ID from an argument (role mention, raw ID, or name).
257
- * Fetches guild roles if name is provided.
258
- * @param arg - Role mention (@role), role ID, or role name
259
- * @returns The role ID, or null if not found
260
- */
261
- resolveRoleId(arg: string): Promise<string | null>;
262
- /**
263
- * Fetch a guild member by user ID.
264
- * @param userId - The user ID of the member to fetch
265
- * @returns The guild member, or null if not found
266
- */
267
- fetchMember(userId: string): Promise<GuildMember | null>;
268
- /** Fetch all webhooks in this guild. Returned webhooks do not include the token (cannot send). */
269
- fetchWebhooks(): Promise<Webhook[]>;
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;
270
421
  }
271
422
 
272
423
  /** Options for editing a message (content and/or embeds). */
@@ -276,6 +427,7 @@ interface MessageEditOptions {
276
427
  /** New embeds (replaces existing) */
277
428
  embeds?: (APIEmbed | EmbedBuilder)[];
278
429
  }
430
+
279
431
  /** Represents a message in a channel. */
280
432
  declare class Message extends Base {
281
433
  readonly client: Client;
@@ -288,6 +440,25 @@ declare class Message extends Base {
288
440
  readonly editedAt: Date | null;
289
441
  pinned: boolean;
290
442
  readonly attachments: Collection<string, APIMessageAttachment>;
443
+ readonly type: MessageType;
444
+ readonly flags: number;
445
+ readonly mentionEveryone: boolean;
446
+ readonly tts: boolean;
447
+ readonly embeds: APIEmbed[];
448
+ readonly stickers: APIMessageSticker[];
449
+ readonly reactions: APIMessageReaction[];
450
+ readonly messageReference: APIMessageReference | null;
451
+ readonly messageSnapshots: APIMessageSnapshot[];
452
+ readonly call: APIMessageCall | null;
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;
291
462
  /** Channel where this message was sent. Resolved from cache; null if not cached (e.g. DM channel not in cache). */
292
463
  get channel(): Channel | null;
293
464
  /** Guild where this message was sent. Resolved from cache; null for DMs or if not cached. */
@@ -296,15 +467,13 @@ declare class Message extends Base {
296
467
  constructor(client: Client, data: APIMessage);
297
468
  /**
298
469
  * Send a message to this channel without replying. Use when you want a standalone message.
299
- * @param options - Text content or object with content and/or embeds
470
+ * @param options - Text content or object with content, embeds, and/or files
300
471
  * @example
301
472
  * await message.send('Pong!');
302
473
  * await message.send({ embeds: [embed.toJSON()] });
474
+ * await message.send({ content: 'File', files: [{ name: 'data.txt', data }] });
303
475
  */
304
- send(options: string | {
305
- content?: string;
306
- embeds?: APIEmbed[];
307
- }): Promise<Message>;
476
+ send(options: MessageSendOptions): Promise<Message>;
308
477
  /**
309
478
  * Send a message to a specific channel. Use for logging, forwarding, or sending to another channel in the guild.
310
479
  * @param channelId - Snowflake of the target channel (e.g. log channel ID)
@@ -313,34 +482,43 @@ declare class Message extends Base {
313
482
  * await message.sendTo(logChannelId, 'User ' + message.author.username + ' said: ' + message.content);
314
483
  * await message.sendTo(announceChannelId, { embeds: [embed.toJSON()] });
315
484
  */
316
- sendTo(channelId: string, options: string | {
317
- content?: string;
318
- embeds?: APIEmbed[];
319
- }): Promise<Message>;
485
+ sendTo(channelId: string, options: MessageSendOptions): Promise<Message>;
320
486
  /**
321
487
  * Reply to this message.
322
- * @param options - Text content or object with content and/or embeds
488
+ * @param options - Text content or object with content, embeds, and/or files
323
489
  */
324
- reply(options: string | {
325
- content?: string;
326
- embeds?: APIEmbed[];
327
- }): Promise<Message>;
490
+ reply(options: MessageSendOptions): Promise<Message>;
328
491
  /**
329
492
  * Edit this message. Only the author (or admins) can edit.
330
493
  * @param options - New content and/or embeds
331
494
  */
332
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;
333
506
  /**
334
507
  * Re-fetch this message from the API to get the latest content, embeds, reactions, etc.
335
508
  * Use when you have a stale Message (e.g. from an old event or cache) and need fresh data.
336
- * @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
337
511
  * @example
338
512
  * const updated = await message.fetch();
339
- * if (updated) console.log('Latest content:', updated.content);
513
+ * console.log('Latest content:', updated.content);
340
514
  */
341
- fetch(): Promise<Message | null>;
515
+ fetch(): Promise<Message>;
342
516
  /** Delete this message. */
343
517
  delete(): Promise<void>;
518
+ /** Pin this message to the channel. Requires Manage Messages permission. */
519
+ pin(): Promise<void>;
520
+ /** Unpin this message from the channel. Requires Manage Messages permission. */
521
+ unpin(): Promise<void>;
344
522
  /**
345
523
  * Format emoji for reaction API: unicode string or "name:id" for custom.
346
524
  * For string resolution (e.g. :name:), use client.resolveEmoji; Message methods resolve automatically when guildId is available.
@@ -380,6 +558,20 @@ declare class Message extends Base {
380
558
  id?: string;
381
559
  animated?: boolean;
382
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[]>;
383
575
  }
384
576
 
385
577
  /** Represents a user (or bot) on Fluxer. */
@@ -391,13 +583,22 @@ declare class User extends Base {
391
583
  globalName: string | null;
392
584
  avatar: string | null;
393
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;
394
594
  /** @param data - API user from message author, GET /users/{id}, or GET /users/@me */
395
595
  constructor(client: Client, data: APIUserPartial);
396
596
  /** Update mutable fields from fresh API data. Used by getOrCreateUser cache. */
397
597
  _patch(data: APIUserPartial): void;
398
598
  /**
399
599
  * Get the URL for this user's avatar.
400
- * @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)
401
602
  */
402
603
  avatarURL(options?: {
403
604
  size?: number;
@@ -406,7 +607,16 @@ declare class User extends Base {
406
607
  /** Get the avatar URL, or the default avatar if none set. */
407
608
  displayAvatarURL(options?: {
408
609
  size?: number;
610
+ extension?: string;
409
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;
410
620
  /** Returns a mention string (e.g. `<@123456>`). */
411
621
  toString(): string;
412
622
  /**
@@ -418,10 +628,7 @@ declare class User extends Base {
418
628
  * Send a DM to this user.
419
629
  * Convenience method that creates the DM channel and sends the message.
420
630
  */
421
- send(options: string | {
422
- content?: string;
423
- embeds?: unknown[];
424
- }): Promise<Message>;
631
+ send(options: MessageSendOptions): Promise<Message>;
425
632
  }
426
633
 
427
634
  /** Represents a member of a guild. */
@@ -434,12 +641,42 @@ declare class GuildMember extends Base {
434
641
  readonly roles: string[];
435
642
  readonly joinedAt: Date;
436
643
  communicationDisabledUntil: Date | null;
644
+ readonly mute: boolean;
645
+ readonly deaf: boolean;
646
+ readonly avatar: string | null;
647
+ readonly banner: string | null;
648
+ readonly accentColor: number | null;
649
+ readonly profileFlags: number | null;
437
650
  /** @param data - API guild member from GET /guilds/{id}/members or GET /guilds/{id}/members/{user_id} */
438
651
  constructor(client: Client, data: APIGuildMember & {
439
652
  guild_id?: string;
440
653
  }, guild: Guild);
441
654
  /** Nickname, or global name, or username. */
442
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;
443
680
  /**
444
681
  * Add a role to this member.
445
682
  * @param roleId - The role ID to add
@@ -452,27 +689,276 @@ declare class GuildMember extends Base {
452
689
  * Requires Manage Roles permission.
453
690
  */
454
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;
455
716
  }
456
717
 
457
- /** Represents a reaction added to or removed from a message. */
458
- declare class MessageReaction extends Base {
718
+ /** Represents a role in a guild. */
719
+ declare class Role extends Base {
459
720
  readonly client: Client;
460
- readonly messageId: string;
461
- readonly channelId: string;
462
- readonly guildId: string | null;
463
- readonly emoji: GatewayReactionEmoji;
464
- /** Raw gateway payload for low-level access. */
465
- readonly _data: GatewayMessageReactionAddDispatchData | GatewayMessageReactionRemoveDispatchData;
466
- constructor(client: Client, data: GatewayMessageReactionAddDispatchData | GatewayMessageReactionRemoveDispatchData);
467
- /** Emoji as a string: unicode or "name:id" for custom. */
468
- get emojiIdentifier(): string;
469
- /** Guild where this reaction was added. Resolved from cache; null for DMs or if not cached. */
470
- get guild(): Guild | null;
721
+ readonly id: string;
722
+ readonly guildId: string;
723
+ name: string;
724
+ color: number;
725
+ position: number;
726
+ permissions: string;
727
+ hoist: boolean;
728
+ mentionable: boolean;
729
+ unicodeEmoji: string | null;
730
+ /** Separately sorted position for hoisted roles. Null if not set. */
731
+ hoistPosition: number | null;
732
+ /** @param client - The client instance */
733
+ /** @param data - API role from GET /guilds/{id}/roles or gateway role events */
734
+ /** @param guildId - The guild this role belongs to */
735
+ constructor(client: Client, data: APIRole, guildId: string);
736
+ /** Returns a mention string (e.g. `<@&123456>`). */
737
+ toString(): string;
471
738
  /**
472
- * Fetch the message this reaction belongs to.
473
- * Use when you need to edit, delete, or otherwise interact with the message.
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>;
766
+ }
767
+
768
+ /** Represents a Fluxer guild (server). */
769
+ declare class Guild extends Base {
770
+ readonly client: Client;
771
+ readonly id: string;
772
+ name: string;
773
+ icon: string | null;
774
+ banner: string | null;
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;
803
+ members: Collection<string, GuildMember>;
804
+ channels: Collection<string, GuildChannel>;
805
+ roles: Collection<string, Role>;
806
+ /** @param data - API guild from GET /guilds/{id} or gateway GUILD_CREATE */
807
+ constructor(client: Client, data: APIGuild & {
808
+ roles?: APIRole[];
809
+ ownerId?: string;
810
+ });
811
+ /** Get the guild icon URL, or null if no icon. */
812
+ iconURL(options?: {
813
+ size?: number;
814
+ }): string | null;
815
+ /** Get the guild banner URL, or null if no banner. */
816
+ bannerURL(options?: {
817
+ size?: number;
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;
823
+ /**
824
+ * Add a role to a member by user ID. Does not require fetching the member first.
825
+ * @param userId - The user ID of the member
826
+ * @param roleId - The role ID to add (or use guild.resolveRoleId for mention/name resolution)
827
+ * Requires Manage Roles permission.
828
+ */
829
+ addRoleToMember(userId: string, roleId: string): Promise<void>;
830
+ /**
831
+ * Remove a role from a member by user ID. Does not require fetching the member first.
832
+ * @param userId - The user ID of the member
833
+ * @param roleId - The role ID to remove
834
+ * Requires Manage Roles permission.
835
+ */
836
+ removeRoleFromMember(userId: string, roleId: string): Promise<void>;
837
+ /**
838
+ * Resolve a role ID from an argument (role mention, raw ID, or name).
839
+ * Fetches guild roles if name is provided.
840
+ * @param arg - Role mention (@role), role ID, or role name
841
+ * @returns The role ID, or null if not found
842
+ */
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>;
873
+ /**
874
+ * Fetch a guild member by user ID.
875
+ * @param userId - The user ID of the member to fetch
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
879
+ */
880
+ fetchMember(userId: string): Promise<GuildMember>;
881
+ /**
882
+ * Fetch guild audit logs. Requires View Audit Log permission.
883
+ * @param options - Optional limit, before, after, user_id, action_type for filtering
474
884
  */
475
- fetchMessage(): Promise<Message | null>;
885
+ fetchAuditLogs(options?: {
886
+ limit?: number;
887
+ before?: string;
888
+ after?: string;
889
+ userId?: string;
890
+ actionType?: number;
891
+ }): Promise<APIGuildAuditLog>;
892
+ /** Fetch all webhooks in this guild. Returned webhooks do not include the token (cannot send). */
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>;
930
+ }
931
+
932
+ /** Represents an invite to a guild or channel. */
933
+ declare class Invite extends Base {
934
+ readonly client: Client;
935
+ readonly code: string;
936
+ readonly type: number;
937
+ readonly guild: APIGuildPartial;
938
+ readonly channel: APIChannelPartial;
939
+ readonly inviter: User | null;
940
+ readonly memberCount: number | null;
941
+ readonly presenceCount: number | null;
942
+ readonly expiresAt: string | null;
943
+ readonly temporary: boolean | null;
944
+ readonly createdAt: string | null;
945
+ readonly uses: number | null;
946
+ readonly maxUses: number | null;
947
+ readonly maxAge: number | null;
948
+ /** @param data - API invite from GET /invites/{code}, channel/guild invite list, or gateway INVITE_CREATE */
949
+ constructor(client: Client, data: APIInvite);
950
+ /** Full invite URL (https://fluxer.gg/{code} or instance-specific). */
951
+ get url(): string;
952
+ /**
953
+ * Resolve the guild from cache if available.
954
+ * @returns The guild, or null if not cached
955
+ */
956
+ getGuild(): Guild | null;
957
+ /**
958
+ * Delete this invite.
959
+ * Requires Manage Guild or Create Instant Invite permission.
960
+ */
961
+ delete(): Promise<void>;
476
962
  }
477
963
 
478
964
  /** Minimal message data for MessageDelete when the full message is not available. */
@@ -492,37 +978,37 @@ declare class ChannelManager extends Collection<string, Channel> {
492
978
  /**
493
979
  * Fetch a channel by ID from the API (or return from cache if present).
494
980
  * @param channelId - Snowflake of the channel
495
- * @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
496
983
  * @example
497
984
  * const channel = await client.channels.fetch(channelId);
498
985
  * if (channel?.isSendable()) await channel.send('Hello!');
499
986
  */
500
- fetch(channelId: string): Promise<Channel | null>;
987
+ fetch(channelId: string): Promise<Channel>;
501
988
  /**
502
989
  * Fetch a message by ID from the API.
503
990
  * @param channelId - Snowflake of the channel
504
991
  * @param messageId - Snowflake of the message
505
- * @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
506
994
  * @deprecated Use channel.messages.fetch(messageId). Prefer (await client.channels.fetch(channelId))?.messages?.fetch(messageId).
507
995
  * @example
508
996
  * const channel = await client.channels.fetch(channelId);
509
997
  * const message = await channel?.messages?.fetch(messageId);
510
998
  */
511
- fetchMessage(channelId: string, messageId: string): Promise<Message | null>;
999
+ fetchMessage(channelId: string, messageId: string): Promise<Message>;
512
1000
  /**
513
1001
  * Send a message to a channel by ID. Works even when the channel is not cached.
514
1002
  * Skips the fetch when you only need to send.
515
1003
  * @param channelId - Snowflake of the channel (text channel or DM)
516
- * @param payload - Text content or object with content and/or embeds
1004
+ * @param payload - Text content or object with content, embeds, and/or files
517
1005
  * @returns The created message
518
1006
  * @example
519
1007
  * await client.channels.send(logChannelId, 'User joined!');
520
1008
  * await client.channels.send(channelId, { embeds: [embed.toJSON()] });
1009
+ * await client.channels.send(channelId, { content: 'Report', files: [{ name: 'log.txt', data }] });
521
1010
  */
522
- send(channelId: string, payload: string | {
523
- content?: string;
524
- embeds?: _fluxerjs_types.APIEmbed[];
525
- }): Promise<Message>;
1011
+ send(channelId: string, payload: MessageSendOptions): Promise<Message>;
526
1012
  }
527
1013
 
528
1014
  /**
@@ -561,8 +1047,19 @@ interface ClientOptions {
561
1047
  declare class ClientUser extends User {
562
1048
  readonly client: Client;
563
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>;
564
1060
  }
565
1061
 
1062
+ /** Event name constants for client.on(Events.X, handler). Use with ClientEvents for typed callbacks. */
566
1063
  declare const Events: {
567
1064
  readonly Ready: "ready";
568
1065
  readonly MessageCreate: "messageCreate";
@@ -609,6 +1106,10 @@ declare const Events: {
609
1106
  readonly Debug: "debug";
610
1107
  };
611
1108
 
1109
+ /**
1110
+ * Callback parameter types for client events. Use with client.on(Events.X, handler).
1111
+ * @see Events
1112
+ */
612
1113
  interface ClientEvents {
613
1114
  [Events.Ready]: [];
614
1115
  [Events.MessageCreate]: [message: Message];
@@ -619,11 +1120,19 @@ interface ClientEvents {
619
1120
  [Events.MessageDelete]: [message: PartialMessage];
620
1121
  [Events.MessageReactionAdd]: [
621
1122
  reaction: MessageReaction,
622
- user: User
1123
+ user: User,
1124
+ messageId: string,
1125
+ channelId: string,
1126
+ emoji: GatewayReactionEmoji,
1127
+ userId: string
623
1128
  ];
624
1129
  [Events.MessageReactionRemove]: [
625
1130
  reaction: MessageReaction,
626
- user: User
1131
+ user: User,
1132
+ messageId: string,
1133
+ channelId: string,
1134
+ emoji: GatewayReactionEmoji,
1135
+ userId: string
627
1136
  ];
628
1137
  [Events.MessageReactionRemoveAll]: [data: GatewayMessageReactionRemoveAllDispatchData];
629
1138
  [Events.MessageReactionRemoveEmoji]: [data: GatewayMessageReactionRemoveEmojiDispatchData];
@@ -656,28 +1165,32 @@ interface ClientEvents {
656
1165
  [Events.MessageDeleteBulk]: [
657
1166
  data: _fluxerjs_types.GatewayMessageDeleteBulkDispatchData
658
1167
  ];
659
- [Events.GuildBanAdd]: [data: _fluxerjs_types.GatewayGuildBanAddDispatchData];
660
- [Events.GuildBanRemove]: [data: _fluxerjs_types.GatewayGuildBanRemoveDispatchData];
661
- [Events.GuildEmojisUpdate]: [data: unknown];
662
- [Events.GuildStickersUpdate]: [data: unknown];
663
- [Events.GuildIntegrationsUpdate]: [data: unknown];
1168
+ [Events.GuildBanAdd]: [ban: GuildBan];
1169
+ [Events.GuildBanRemove]: [ban: GuildBan];
1170
+ [Events.GuildEmojisUpdate]: [data: GatewayGuildEmojisUpdateDispatchData];
1171
+ [Events.GuildStickersUpdate]: [data: GatewayGuildStickersUpdateDispatchData];
1172
+ [Events.GuildIntegrationsUpdate]: [data: GatewayGuildIntegrationsUpdateDispatchData];
664
1173
  [Events.GuildRoleCreate]: [data: _fluxerjs_types.GatewayGuildRoleCreateDispatchData];
665
1174
  [Events.GuildRoleUpdate]: [data: _fluxerjs_types.GatewayGuildRoleUpdateDispatchData];
666
1175
  [Events.GuildRoleDelete]: [data: _fluxerjs_types.GatewayGuildRoleDeleteDispatchData];
667
- [Events.GuildScheduledEventCreate]: [data: unknown];
668
- [Events.GuildScheduledEventUpdate]: [data: unknown];
669
- [Events.GuildScheduledEventDelete]: [data: unknown];
670
- [Events.ChannelPinsUpdate]: [data: unknown];
671
- [Events.InviteCreate]: [data: unknown];
672
- [Events.InviteDelete]: [data: unknown];
1176
+ [Events.GuildScheduledEventCreate]: [data: GatewayGuildScheduledEventCreateDispatchData];
1177
+ [Events.GuildScheduledEventUpdate]: [data: GatewayGuildScheduledEventUpdateDispatchData];
1178
+ [Events.GuildScheduledEventDelete]: [data: GatewayGuildScheduledEventDeleteDispatchData];
1179
+ [Events.ChannelPinsUpdate]: [data: GatewayChannelPinsUpdateDispatchData];
1180
+ [Events.InviteCreate]: [invite: Invite];
1181
+ [Events.InviteDelete]: [data: _fluxerjs_types.GatewayInviteDeleteDispatchData];
673
1182
  [Events.TypingStart]: [data: _fluxerjs_types.GatewayTypingStartDispatchData];
674
1183
  [Events.UserUpdate]: [data: _fluxerjs_types.GatewayUserUpdateDispatchData];
675
- [Events.PresenceUpdate]: [data: unknown];
676
- [Events.WebhooksUpdate]: [data: unknown];
1184
+ [Events.PresenceUpdate]: [data: GatewayPresenceUpdateDispatchData];
1185
+ [Events.WebhooksUpdate]: [data: GatewayWebhooksUpdateDispatchData];
677
1186
  [Events.Resumed]: [];
678
1187
  [Events.Error]: [error: Error];
679
1188
  [Events.Debug]: [message: string];
680
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
+ };
681
1194
  /** Main Fluxer bot client. Connects to the gateway, emits events, and provides REST access. */
682
1195
  declare class Client extends EventEmitter {
683
1196
  readonly options: ClientOptions;
@@ -685,7 +1198,11 @@ declare class Client extends EventEmitter {
685
1198
  readonly guilds: GuildManager;
686
1199
  readonly channels: ChannelManager;
687
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. */
688
1204
  user: ClientUser | null;
1205
+ /** Timestamp when the client became ready. Null until READY is received. */
689
1206
  readyAt: Date | null;
690
1207
  private _ws;
691
1208
  /** @param options - Token, REST config, WebSocket, presence, etc. */
@@ -707,13 +1224,14 @@ declare class Client extends EventEmitter {
707
1224
  * Fetch a message by channel and message ID. Use when you have IDs (e.g. from a DB).
708
1225
  * @param channelId - Snowflake of the channel
709
1226
  * @param messageId - Snowflake of the message
710
- * @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
711
1229
  * @deprecated Use channel.messages.fetch(messageId). For IDs-only: (await client.channels.fetch(channelId))?.messages?.fetch(messageId)
712
1230
  * @example
713
1231
  * const channel = await client.channels.fetch(channelId);
714
1232
  * const message = await channel?.messages?.fetch(messageId);
715
1233
  */
716
- fetchMessage(channelId: string, messageId: string): Promise<Message | null>;
1234
+ fetchMessage(channelId: string, messageId: string): Promise<Message>;
717
1235
  /**
718
1236
  * Send a message to any channel by ID. Shorthand for client.channels.send().
719
1237
  * Works even when the channel is not cached.
@@ -750,13 +1268,137 @@ declare class Client extends EventEmitter {
750
1268
  static get Routes(): typeof Routes;
751
1269
  }
752
1270
 
1271
+ /** Represents a custom emoji in a guild. */
1272
+ declare class GuildEmoji extends Base {
1273
+ readonly client: Client;
1274
+ readonly id: string;
1275
+ readonly guildId: string;
1276
+ name: string;
1277
+ readonly animated: boolean;
1278
+ /** @param data - API emoji from GET /guilds/{id}/emojis or guild emoji events */
1279
+ constructor(client: Client, data: APIEmoji & {
1280
+ guild_id?: string;
1281
+ }, guildId: string);
1282
+ /** CDN URL for this emoji image. */
1283
+ get url(): string;
1284
+ /** Emoji identifier for use in reactions: `name:id` */
1285
+ get identifier(): string;
1286
+ /** Delete this emoji. Requires Manage Emojis and Stickers permission. */
1287
+ delete(): Promise<void>;
1288
+ /**
1289
+ * Edit this emoji's name.
1290
+ * Requires Manage Emojis and Stickers permission.
1291
+ */
1292
+ edit(options: {
1293
+ name: string;
1294
+ }): Promise<GuildEmoji>;
1295
+ }
1296
+
1297
+ /** Represents a custom sticker in a guild. */
1298
+ declare class GuildSticker extends Base {
1299
+ readonly client: Client;
1300
+ readonly id: string;
1301
+ readonly guildId: string;
1302
+ name: string;
1303
+ description: string;
1304
+ readonly tags: string[];
1305
+ readonly animated: boolean;
1306
+ /** @param data - API sticker from GET /guilds/{id}/stickers or guild sticker events */
1307
+ constructor(client: Client, data: APISticker & {
1308
+ guild_id?: string;
1309
+ }, guildId: string);
1310
+ /** CDN URL for this sticker image. */
1311
+ get url(): string;
1312
+ /** Delete this sticker. Requires Manage Emojis and Stickers permission. */
1313
+ delete(): Promise<void>;
1314
+ /**
1315
+ * Edit this sticker's name and/or description.
1316
+ * Requires Manage Emojis and Stickers permission.
1317
+ */
1318
+ edit(options: {
1319
+ name?: string;
1320
+ description?: string;
1321
+ }): Promise<GuildSticker>;
1322
+ }
1323
+
1324
+ interface FluxerErrorOptions {
1325
+ code?: string;
1326
+ cause?: Error;
1327
+ }
753
1328
  declare class FluxerError extends Error {
754
- constructor(message: string);
1329
+ readonly code?: string;
1330
+ constructor(message: string, options?: FluxerErrorOptions);
755
1331
  }
756
1332
 
757
1333
  declare const ErrorCodes: {
758
1334
  readonly ClientNotReady: "CLIENT_NOT_READY";
759
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";
760
1341
  };
761
1342
 
762
- export { Base, CategoryChannel, Channel, ChannelManager, Client, type ClientEvents, ClientUser, DMChannel, ErrorCodes, Events, FluxerError, Guild, GuildChannel, GuildMember, 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 };