@stoatx/client 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -38,16 +38,22 @@ __export(index_exports, {
38
38
  Client: () => Client,
39
39
  ClientUser: () => ClientUser,
40
40
  Collection: () => Collection,
41
+ Collector: () => Collector,
41
42
  DMChannel: () => DMChannel,
42
43
  EmbedBuilder: () => EmbedBuilder,
44
+ Emoji: () => Emoji,
45
+ EmojiManager: () => EmojiManager,
43
46
  GatewayManager: () => GatewayManager,
44
47
  Member: () => Member,
45
48
  MemberManager: () => MemberManager,
46
49
  Message: () => Message,
50
+ MessageCollector: () => MessageCollector,
47
51
  MessageManager: () => MessageManager,
52
+ MessageReaction: () => MessageReaction,
48
53
  PermissionFlags: () => PermissionFlags,
49
54
  Permissions: () => Permissions,
50
55
  RESTManager: () => RESTManager,
56
+ ReactionCollector: () => ReactionCollector,
51
57
  Role: () => Role,
52
58
  RoleManager: () => RoleManager,
53
59
  Server: () => Server,
@@ -65,7 +71,7 @@ __export(index_exports, {
65
71
  module.exports = __toCommonJS(index_exports);
66
72
 
67
73
  // src/client/Client.ts
68
- var import_events = require("events");
74
+ var import_events2 = require("events");
69
75
 
70
76
  // src/gateway/GatewayManager.ts
71
77
  var import_ws = __toESM(require("ws"), 1);
@@ -106,7 +112,7 @@ var Base = class _Base {
106
112
  };
107
113
 
108
114
  // src/structures/Message.ts
109
- var util = __toESM(require("util"), 1);
115
+ var util2 = __toESM(require("util"), 1);
110
116
 
111
117
  // src/structures/Attachment.ts
112
118
  var Attachment = class extends Base {
@@ -153,6 +159,306 @@ var Attachment = class extends Base {
153
159
 
154
160
  // src/structures/Message.ts
155
161
  var import_ulid = require("ulid");
162
+
163
+ // src/utils/Collector.ts
164
+ var import_events = require("events");
165
+
166
+ // src/utils/Collection.ts
167
+ var Collection = class _Collection extends Map {
168
+ limit;
169
+ constructor(limit = Infinity) {
170
+ super();
171
+ this.limit = limit;
172
+ }
173
+ /**
174
+ * Overrides the default set method to enforce the maximum cache size.
175
+ */
176
+ set(key, value) {
177
+ if (this.limit === 0) return this;
178
+ if (this.size >= this.limit && !this.has(key)) {
179
+ const oldestKey = this.keys().next().value;
180
+ if (oldestKey !== void 0) {
181
+ this.delete(oldestKey);
182
+ }
183
+ }
184
+ return super.set(key, value);
185
+ }
186
+ /**
187
+ * Finds the first item where the given function returns true.
188
+ */
189
+ find(fn) {
190
+ for (const [key, val] of this) {
191
+ if (fn(val, key, this)) return val;
192
+ }
193
+ return void 0;
194
+ }
195
+ /**
196
+ * Returns a new Collection containing only the items where the function returns true.
197
+ */
198
+ filter(fn) {
199
+ const results = new _Collection();
200
+ for (const [key, val] of this) {
201
+ if (fn(val, key, this)) results.set(key, val);
202
+ }
203
+ return results;
204
+ }
205
+ /**
206
+ * Maps each item to a new array of values.
207
+ */
208
+ map(fn) {
209
+ const results = [];
210
+ for (const [key, val] of this) {
211
+ results.push(fn(val, key, this));
212
+ }
213
+ return results;
214
+ }
215
+ /**
216
+ * Gets the very first value in the Collection (based on insertion order).
217
+ */
218
+ first() {
219
+ return this.values().next().value;
220
+ }
221
+ /**
222
+ * Gets the very last value in the Collection.
223
+ */
224
+ last() {
225
+ const arr = Array.from(this.values());
226
+ return arr[arr.length - 1];
227
+ }
228
+ /**
229
+ * Checks if at least one item matches the condition.
230
+ */
231
+ some(fn) {
232
+ for (const [key, val] of this) {
233
+ if (fn(val, key, this)) return true;
234
+ }
235
+ return false;
236
+ }
237
+ };
238
+
239
+ // src/utils/Collector.ts
240
+ var Collector = class extends import_events.EventEmitter {
241
+ client;
242
+ filter;
243
+ options;
244
+ collected;
245
+ ended = false;
246
+ _timeout = null;
247
+ _idletimeout = null;
248
+ constructor(client, options = {}) {
249
+ super();
250
+ this.client = client;
251
+ this.options = options;
252
+ this.filter = options.filter ?? (() => true);
253
+ this.collected = new Collection();
254
+ if (options.time) {
255
+ this._timeout = setTimeout(() => this.stop("time"), options.time);
256
+ }
257
+ if (options.idle) {
258
+ this._idletimeout = setTimeout(() => this.stop("idle"), options.idle);
259
+ }
260
+ }
261
+ /**
262
+ * Evaluates an item and possibly passes it to the collector
263
+ */
264
+ handleCollect(item, ...args) {
265
+ if (this.ended) return;
266
+ if (!this.filter(item, ...args)) return;
267
+ const key = this.collect(item, ...args);
268
+ if (key !== null && key !== void 0) {
269
+ this.collected.set(key, item);
270
+ this.emit("collect", item, ...args);
271
+ if (this._idletimeout) {
272
+ clearTimeout(this._idletimeout);
273
+ this._idletimeout = setTimeout(() => this.stop("idle"), this.options.idle);
274
+ }
275
+ this.checkEnd();
276
+ }
277
+ }
278
+ /**
279
+ * Evaluates an item and possibly removes it from the collector
280
+ */
281
+ handleDispose(item, ...args) {
282
+ if (this.ended) return;
283
+ if (!this.options.dispose) return;
284
+ const key = this.dispose(item, ...args);
285
+ if (key !== null && key !== void 0) {
286
+ this.collected.delete(key);
287
+ this.emit("dispose", item, ...args);
288
+ this.checkEnd();
289
+ }
290
+ }
291
+ /**
292
+ * Stops the collector.
293
+ */
294
+ stop(reason = "user") {
295
+ if (this.ended) return;
296
+ this.ended = true;
297
+ if (this._timeout) clearTimeout(this._timeout);
298
+ if (this._idletimeout) clearTimeout(this._idletimeout);
299
+ this.removeAllListeners("collect");
300
+ this.removeAllListeners("dispose");
301
+ this.emit("end", this.collected, reason);
302
+ }
303
+ /**
304
+ * Check if we should end upon collecting/disposing
305
+ */
306
+ checkEnd() {
307
+ const reason = this.endReason();
308
+ if (reason) this.stop(reason);
309
+ }
310
+ /**
311
+ * Check if there's a reason to end
312
+ */
313
+ endReason() {
314
+ return null;
315
+ }
316
+ /**
317
+ * Allows iterating over collected items asynchronously.
318
+ * @example
319
+ * for await (const [id, message] of collector) {
320
+ * console.log(`Received message: ${message.content}`);
321
+ * }
322
+ */
323
+ async *[Symbol.asyncIterator]() {
324
+ const queue = [];
325
+ let resolve = null;
326
+ const onCollect = (item, ...args) => {
327
+ const key = this.collect(item, ...args);
328
+ if (key !== null && key !== void 0) {
329
+ queue.push([key, item]);
330
+ }
331
+ if (resolve) {
332
+ resolve();
333
+ resolve = null;
334
+ }
335
+ };
336
+ const onEnd = () => {
337
+ if (resolve) {
338
+ resolve();
339
+ resolve = null;
340
+ }
341
+ };
342
+ this.on("collect", onCollect);
343
+ this.on("end", onEnd);
344
+ try {
345
+ while (true) {
346
+ if (queue.length > 0) {
347
+ yield queue.shift();
348
+ } else if (this.ended) {
349
+ break;
350
+ } else {
351
+ await new Promise((res) => {
352
+ resolve = res;
353
+ });
354
+ }
355
+ }
356
+ } finally {
357
+ this.removeListener("collect", onCollect);
358
+ this.removeListener("end", onEnd);
359
+ }
360
+ }
361
+ };
362
+
363
+ // src/structures/MessageReaction.ts
364
+ var util = __toESM(require("util"), 1);
365
+ var MessageReaction = class {
366
+ constructor(client, data) {
367
+ this.client = client;
368
+ this.message = data.message;
369
+ this.emoji = this.client.emojis.cache.get(data.emojiId) || data.emojiId;
370
+ this.users = new Collection();
371
+ if (data.users) {
372
+ for (const userId of data.users) {
373
+ const user = this.client.users.cache.get(userId) || { id: userId };
374
+ this.users.set(userId, user);
375
+ }
376
+ }
377
+ }
378
+ message;
379
+ emoji;
380
+ users;
381
+ get count() {
382
+ return this.users.size;
383
+ }
384
+ async remove() {
385
+ if (this.message instanceof Message) {
386
+ const emojiId = typeof this.emoji === "string" ? this.emoji : this.emoji.id;
387
+ await this.message.removeReaction(emojiId);
388
+ }
389
+ }
390
+ [util.inspect.custom]() {
391
+ const data = {
392
+ messageId: this.message.id,
393
+ emoji: this.emoji,
394
+ count: this.count,
395
+ users: Array.from(this.users.keys())
396
+ };
397
+ return `MessageReaction ${util.inspect(data)}`;
398
+ }
399
+ };
400
+
401
+ // src/utils/ReactionCollector.ts
402
+ var ReactionCollector = class extends Collector {
403
+ constructor(message, options = {}) {
404
+ super(message.client, options);
405
+ this.message = message;
406
+ this.messageId = message.id;
407
+ const boundHandleCollect = this.handleMessageReact.bind(this);
408
+ const boundHandleDispose = this.handleMessageUnreact.bind(this);
409
+ this.client.on("messageReact", boundHandleCollect);
410
+ this.client.on("messageUnreact", boundHandleDispose);
411
+ this.once("end", () => {
412
+ this.client.removeListener("messageReact", boundHandleCollect);
413
+ this.client.removeListener("messageUnreact", boundHandleDispose);
414
+ });
415
+ }
416
+ messageId;
417
+ total = 0;
418
+ users = /* @__PURE__ */ new Set();
419
+ collect(reaction) {
420
+ if (reaction.message.id !== this.messageId) return null;
421
+ return typeof reaction.emoji === "string" ? reaction.emoji : reaction.emoji.id;
422
+ }
423
+ dispose(reaction) {
424
+ if (reaction.message.id !== this.messageId) return null;
425
+ return typeof reaction.emoji === "string" ? reaction.emoji : reaction.emoji.id;
426
+ }
427
+ handleMessageReact(message, emojiId, userId) {
428
+ if (message.id !== this.messageId) return;
429
+ let reaction = this.collected.get(emojiId);
430
+ if (!reaction) {
431
+ reaction = new MessageReaction(this.client, { message, emojiId, users: [userId] });
432
+ } else {
433
+ const user = this.client.users.cache.get(userId) || { id: userId };
434
+ reaction.users.set(userId, user);
435
+ }
436
+ super.handleCollect(reaction);
437
+ if (!this.ended && this.collected.has(emojiId)) {
438
+ this.total++;
439
+ this.users.add(userId);
440
+ this.checkEnd();
441
+ }
442
+ }
443
+ handleMessageUnreact(message, emojiId, userId) {
444
+ if (message.id !== this.messageId) return;
445
+ const reaction = this.collected.get(emojiId);
446
+ if (reaction) {
447
+ reaction.users.delete(userId);
448
+ if (reaction.users.size === 0) {
449
+ super.handleDispose(reaction);
450
+ }
451
+ }
452
+ }
453
+ endReason() {
454
+ const options = this.options;
455
+ if (options.max && this.total >= options.max) return "limit";
456
+ if (options.maxUsers && this.users.size >= options.maxUsers) return "userLimit";
457
+ return null;
458
+ }
459
+ };
460
+
461
+ // src/structures/Message.ts
156
462
  var Message = class extends Base {
157
463
  content = null;
158
464
  authorId;
@@ -166,7 +472,7 @@ var Message = class extends Base {
166
472
  masquerade = null;
167
473
  mentions = [];
168
474
  pinned = false;
169
- reactions = [];
475
+ reactions = {};
170
476
  replies = [];
171
477
  role_mentions = [];
172
478
  constructor(client, data) {
@@ -234,6 +540,78 @@ var Message = class extends Base {
234
540
  if (!channel) channel = await this.client.channels.fetch(this.channelId);
235
541
  await channel.messages.unpin(this.id);
236
542
  }
543
+ /**
544
+ * React to this message
545
+ * @param reaction The emoji to react with. Can be a Unicode emoji or a custom emoji ID.
546
+ * @throws {Error} If the API request fails.
547
+ * @example
548
+ * await message.react("👍");
549
+ * await message.react("customEmojiId");
550
+ */
551
+ async react(reaction) {
552
+ let channel = this.channel;
553
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
554
+ await channel.messages.react(this.id, reaction);
555
+ }
556
+ /**
557
+ * Remove a reaction from this message
558
+ * @param reaction The emoji to remove. Can be a Unicode emoji or a custom emoji ID.
559
+ * @param userId The ID of the user whose reaction to remove. If not provided, removes the current user's reaction.
560
+ * @param removeAll Remove all reactions of this type.
561
+ * @throws {Error} If both userId and removeAll are provided, or if the API request fails.
562
+ * @example
563
+ * // Remove the current user's reaction
564
+ * await message.removeReaction("👍");
565
+ * // Remove a specific user's reaction
566
+ * await message.removeReaction("👍", userId);
567
+ * // Remove all reactions of this type
568
+ * await message.removeReaction("👍", undefined, true);
569
+ */
570
+ async removeReaction(reaction, userId, removeAll) {
571
+ let channel = this.channel;
572
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
573
+ await channel.messages.removeReaction(this.id, reaction, userId, removeAll);
574
+ }
575
+ /**
576
+ * Remove all reactions from this message
577
+ * @throws {Error} If the API request fails.
578
+ * @example
579
+ * await message.clearReactions();
580
+ */
581
+ async clearReactions() {
582
+ let channel = this.channel;
583
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
584
+ await channel.messages.clearReactions(this.id);
585
+ }
586
+ /**
587
+ * Creates a ReactionCollector to collect reactions on this message.
588
+ * @param options The options for the collector.
589
+ * @returns A new ReactionCollector instance.
590
+ * @example
591
+ * const collector = message.createReactionCollector({ time: 15000 });
592
+ * collector.on('collect', (reaction) => console.log(`Collected ${reaction.emojiId} from ${reaction.userId}`));
593
+ * collector.on('end', (collected) => console.log(`Collected ${collected.size} items`));
594
+ */
595
+ createReactionCollector(options) {
596
+ return new ReactionCollector(this, options);
597
+ }
598
+ /**
599
+ * Awaits reactions on this message.
600
+ * @param options The options for the collector.
601
+ * @returns A promise that resolves to a collection of reactions collected.
602
+ * @example
603
+ * // Await reactions
604
+ * const filter = (reaction) => reaction.emoji.id === '123' && reaction.users.has(author.id);
605
+ * message.awaitReactions({ filter, max: 1, time: 60000 })
606
+ * .then(collected => console.log(collected.size))
607
+ * .catch(console.error);
608
+ */
609
+ awaitReactions(options) {
610
+ return new Promise((resolve) => {
611
+ const collector = this.createReactionCollector(options);
612
+ collector.once("end", (collected) => resolve(collected));
613
+ });
614
+ }
237
615
  /** Gets the Channel object from cache */
238
616
  get channel() {
239
617
  return this.client.channels.cache.get(this.channelId);
@@ -271,7 +649,9 @@ var Message = class extends Base {
271
649
  if (data.pinned !== void 0) this.pinned = data.pinned;
272
650
  if (data.embeds !== void 0) this.embeds = data.embeds;
273
651
  if (data.flags !== void 0) this.flags = data.flags;
274
- if (data.reactions !== void 0) this.reactions = data.reactions;
652
+ if (data.reactions !== void 0) {
653
+ this.reactions = Array.isArray(data.reactions) ? {} : data.reactions;
654
+ }
275
655
  if (data.interactions !== void 0) {
276
656
  if (data.interactions) {
277
657
  this.interactions = {
@@ -284,7 +664,7 @@ var Message = class extends Base {
284
664
  }
285
665
  }
286
666
  // This tells Node.js exactly how to print this object in console.log()
287
- [util.inspect.custom](depth, options, inspect10) {
667
+ [util2.inspect.custom](depth, options, inspect12) {
288
668
  const { client, authorId, channelId, ...props } = this;
289
669
  const data = {
290
670
  ...props,
@@ -293,7 +673,7 @@ var Message = class extends Base {
293
673
  server: this.server,
294
674
  member: this.member
295
675
  };
296
- return `${this.constructor.name} ${inspect10(data, { ...options, depth: depth ?? options.depth })}`;
676
+ return `${this.constructor.name} ${inspect12(data, { ...options, depth: depth ?? options.depth })}`;
297
677
  }
298
678
  };
299
679
 
@@ -455,6 +835,17 @@ var GatewayManager = class {
455
835
  }
456
836
  }
457
837
  }
838
+ if (payload.emojis) {
839
+ for (const rawEmoji of payload.emojis) {
840
+ const emoji = this.client.emojis._add(rawEmoji);
841
+ if (rawEmoji.parent && rawEmoji.parent.type === "Server") {
842
+ const server = this.client.servers.cache.get(rawEmoji.parent.id);
843
+ if (server) {
844
+ server.emojis._add(emoji);
845
+ }
846
+ }
847
+ }
848
+ }
458
849
  this.client.emit("ready", payload);
459
850
  break;
460
851
  }
@@ -514,6 +905,60 @@ var GatewayManager = class {
514
905
  }
515
906
  break;
516
907
  }
908
+ case "MessageReact": {
909
+ const channel = this.client.channels.cache.get(payload.channel_id);
910
+ const message = channel?.messages.cache.get(payload.id);
911
+ if (message) {
912
+ if (!message.reactions) message.reactions = {};
913
+ if (!message.reactions[payload.emoji_id]) {
914
+ message.reactions[payload.emoji_id] = [];
915
+ }
916
+ const reactions = message.reactions[payload.emoji_id];
917
+ if (reactions && !reactions.includes(payload.user_id)) {
918
+ reactions.push(payload.user_id);
919
+ }
920
+ }
921
+ this.client.emit(
922
+ "messageReact",
923
+ message || { id: payload.id, channelId: payload.channel_id },
924
+ payload.emoji_id,
925
+ payload.user_id
926
+ );
927
+ break;
928
+ }
929
+ case "MessageUnreact": {
930
+ const channel = this.client.channels.cache.get(payload.channel_id);
931
+ const message = channel?.messages.cache.get(payload.id);
932
+ if (message && message.reactions && message.reactions[payload.emoji_id]) {
933
+ const reactions = message.reactions[payload.emoji_id];
934
+ if (reactions) {
935
+ message.reactions[payload.emoji_id] = reactions.filter((userId) => userId !== payload.user_id);
936
+ if (message.reactions[payload.emoji_id].length === 0) {
937
+ delete message.reactions[payload.emoji_id];
938
+ }
939
+ }
940
+ }
941
+ this.client.emit(
942
+ "messageUnreact",
943
+ message || { id: payload.id, channelId: payload.channel_id },
944
+ payload.emoji_id,
945
+ payload.user_id
946
+ );
947
+ break;
948
+ }
949
+ case "MessageRemoveReaction": {
950
+ const channel = this.client.channels.cache.get(payload.channel_id);
951
+ const message = channel?.messages.cache.get(payload.id);
952
+ if (message && message.reactions) {
953
+ delete message.reactions[payload.emoji_id];
954
+ }
955
+ this.client.emit(
956
+ "messageRemoveReaction",
957
+ message || { id: payload.id, channelId: payload.channel_id },
958
+ payload.emoji_id
959
+ );
960
+ break;
961
+ }
517
962
  case "Pong":
518
963
  this.client.emit("debug", "Received Pong from server.");
519
964
  break;
@@ -590,6 +1035,27 @@ var GatewayManager = class {
590
1035
  }
591
1036
  break;
592
1037
  }
1038
+ case "EmojiCreate": {
1039
+ const emoji = this.client.emojis._add(payload);
1040
+ if (payload.parent?.type === "Server") {
1041
+ const server = this.client.servers.cache.get(payload.parent.id);
1042
+ if (server) {
1043
+ server.emojis._add(emoji);
1044
+ }
1045
+ }
1046
+ break;
1047
+ }
1048
+ case "EmojiDelete": {
1049
+ this.client.emojis.cache.delete(payload.id);
1050
+ for (const server of this.client.servers.cache.values()) {
1051
+ const emoji = server.emojis.cache.get(payload.id);
1052
+ if (emoji) {
1053
+ server.emojis.cache.delete(payload.id);
1054
+ break;
1055
+ }
1056
+ }
1057
+ break;
1058
+ }
593
1059
  case "UserUpdate": {
594
1060
  const existing = this.client.users.cache.get(payload.id);
595
1061
  if (existing) {
@@ -808,89 +1274,16 @@ var RESTManager = class {
808
1274
  patch(endpoint, body) {
809
1275
  return this.makeRequest("PATCH", endpoint, body);
810
1276
  }
811
- delete(endpoint) {
812
- return this.makeRequest("DELETE", endpoint);
1277
+ delete(endpoint, body) {
1278
+ return this.makeRequest("DELETE", endpoint, body);
813
1279
  }
814
1280
  async put(endpoint, body) {
815
1281
  return this.makeRequest("PUT", endpoint, body);
816
1282
  }
817
1283
  };
818
1284
 
819
- // src/utils/Collection.ts
820
- var Collection = class _Collection extends Map {
821
- limit;
822
- constructor(limit = Infinity) {
823
- super();
824
- this.limit = limit;
825
- }
826
- /**
827
- * Overrides the default set method to enforce the maximum cache size.
828
- */
829
- set(key, value) {
830
- if (this.limit === 0) return this;
831
- if (this.size >= this.limit && !this.has(key)) {
832
- const oldestKey = this.keys().next().value;
833
- if (oldestKey !== void 0) {
834
- this.delete(oldestKey);
835
- }
836
- }
837
- return super.set(key, value);
838
- }
839
- /**
840
- * Finds the first item where the given function returns true.
841
- */
842
- find(fn) {
843
- for (const [key, val] of this) {
844
- if (fn(val, key, this)) return val;
845
- }
846
- return void 0;
847
- }
848
- /**
849
- * Returns a new Collection containing only the items where the function returns true.
850
- */
851
- filter(fn) {
852
- const results = new _Collection();
853
- for (const [key, val] of this) {
854
- if (fn(val, key, this)) results.set(key, val);
855
- }
856
- return results;
857
- }
858
- /**
859
- * Maps each item to a new array of values.
860
- */
861
- map(fn) {
862
- const results = [];
863
- for (const [key, val] of this) {
864
- results.push(fn(val, key, this));
865
- }
866
- return results;
867
- }
868
- /**
869
- * Gets the very first value in the Collection (based on insertion order).
870
- */
871
- first() {
872
- return this.values().next().value;
873
- }
874
- /**
875
- * Gets the very last value in the Collection.
876
- */
877
- last() {
878
- const arr = Array.from(this.values());
879
- return arr[arr.length - 1];
880
- }
881
- /**
882
- * Checks if at least one item matches the condition.
883
- */
884
- some(fn) {
885
- for (const [key, val] of this) {
886
- if (fn(val, key, this)) return true;
887
- }
888
- return false;
889
- }
890
- };
891
-
892
1285
  // src/managers/MessageManager.ts
893
- var util2 = __toESM(require("util"), 1);
1286
+ var util3 = __toESM(require("util"), 1);
894
1287
 
895
1288
  // src/managers/BaseManager.ts
896
1289
  var BaseManager = class {
@@ -1046,11 +1439,105 @@ var MessageManager = class extends BaseManager {
1046
1439
  const existing = this.cache.get(id);
1047
1440
  if (existing) existing.pinned = false;
1048
1441
  }
1049
- [util2.inspect.custom]() {
1442
+ /**
1443
+ * React to a message
1444
+ * @param message The MessageResolvable to react to.
1445
+ * @param reaction The emoji to react with. Can be a Unicode emoji or a custom emoji ID.
1446
+ * @throws {Error} If the API request fails.
1447
+ * @example
1448
+ * await channel.messages.react(messageId, "👍");
1449
+ * await channel.messages.react(messageId, "customEmojiId");
1450
+ */
1451
+ async react(message, reaction) {
1452
+ const id = this.resolveId(message);
1453
+ await this.client.rest.put(`/channels/${this.channel.id}/messages/${id}/reactions/${encodeURIComponent(reaction)}`);
1454
+ }
1455
+ /**
1456
+ * Remove a reaction(s) from a message
1457
+ * Requires ManageMessages if changing others' reactions.
1458
+ * @param reaction The emoji to remove. Can be a unicode emoji or a custom emoji ID.
1459
+ * @param message The MessageResolvable to remove the reaction from.
1460
+ * @param userId The ID of the user whose reaction to remove. If not provided, removes the current user's reaction.
1461
+ * @param removeAll Remove all reactions of this type.
1462
+ * @throws {Error} If both userId and removeAll are provided, or if the API request fails.
1463
+ * @example
1464
+ * // Remove the current user's reaction
1465
+ * await channel.messages.removeReaction(messageId, "👍");
1466
+ * // Remove a specific user's reaction
1467
+ * await channel.messages.removeReaction(messageId, "👍", userId);
1468
+ * // Remove all reactions of this type
1469
+ * await channel.messages.removeReaction(messageId, "👍", undefined, true);
1470
+ */
1471
+ async removeReaction(message, reaction, userId, removeAll) {
1472
+ const id = this.resolveId(message);
1473
+ const targetUser = userId ? this.client.users.resolveId(userId) : void 0;
1474
+ const params = new URLSearchParams();
1475
+ if (targetUser) params.append("user_id", targetUser);
1476
+ if (removeAll) params.append("remove_all", "true");
1477
+ const queryString = params.toString();
1478
+ const endpoint = `/channels/${this.channel.id}/messages/${id}/reactions/${encodeURIComponent(reaction)}${queryString ? `?${queryString}` : ""}`;
1479
+ await this.client.rest.delete(endpoint);
1480
+ }
1481
+ /**
1482
+ * Remove all reactions from a message
1483
+ * Requires ManageMessages permission.
1484
+ * @param message The MessageResolvable to clear reactions from.
1485
+ * @throws {Error} If the API request fails.
1486
+ * @example
1487
+ * await channel.messages.clearReactions(messageId);
1488
+ */
1489
+ async clearReactions(message) {
1490
+ const id = this.resolveId(message);
1491
+ await this.client.rest.delete(`/channels/${this.channel.id}/messages/${id}/reactions`);
1492
+ }
1493
+ [util3.inspect.custom]() {
1050
1494
  return this.cache;
1051
1495
  }
1052
1496
  };
1053
1497
 
1498
+ // src/utils/MessageCollector.ts
1499
+ var MessageCollector = class extends Collector {
1500
+ constructor(channel, options = {}) {
1501
+ super(channel.client, options);
1502
+ this.channel = channel;
1503
+ this.channelId = channel.id;
1504
+ const boundHandleCollect = this.handleCollect.bind(this);
1505
+ const boundHandleDispose = this.handleDispose.bind(this);
1506
+ this.client.on("messageCreate", boundHandleCollect);
1507
+ this.client.on("messageDelete", boundHandleDispose);
1508
+ this.once("end", () => {
1509
+ this.client.removeListener("messageCreate", boundHandleCollect);
1510
+ this.client.removeListener("messageDelete", boundHandleDispose);
1511
+ });
1512
+ }
1513
+ channelId;
1514
+ total = 0;
1515
+ processed = 0;
1516
+ collect(message) {
1517
+ if (message.channelId !== this.channelId) return null;
1518
+ return message.id;
1519
+ }
1520
+ dispose(message) {
1521
+ if (message.channelId !== this.channelId) return null;
1522
+ return message.id;
1523
+ }
1524
+ handleCollect(message) {
1525
+ if (message.channelId !== this.channelId) return;
1526
+ this.processed++;
1527
+ super.handleCollect(message);
1528
+ if (!this.ended && this.collected.has(message.id)) {
1529
+ this.total++;
1530
+ this.checkEnd();
1531
+ }
1532
+ }
1533
+ endReason() {
1534
+ const options = this.options;
1535
+ if (options.max && this.total >= options.max) return "limit";
1536
+ if (options.maxProcessed && this.processed >= options.maxProcessed) return "processedLimit";
1537
+ return null;
1538
+ }
1539
+ };
1540
+
1054
1541
  // src/structures/BaseChannel.ts
1055
1542
  var ChannelType = /* @__PURE__ */ ((ChannelType2) => {
1056
1543
  ChannelType2["TEXT"] = "TextChannel";
@@ -1077,12 +1564,36 @@ var BaseChannel = class extends Base {
1077
1564
  async send(contentOrOptions) {
1078
1565
  return this.messages.send(contentOrOptions);
1079
1566
  }
1080
- async fetch(force = true) {
1567
+ /**
1568
+ * Fetch this channel
1569
+ * @param force Whether to skip the cache check and force a direct API request. Defaults to false
1570
+ * @throws {Error} If the API request fails
1571
+ * @returns {BaseChannel}
1572
+ * @example
1573
+ * // Force fetch channel to update its data
1574
+ * await channel.fetch(true);
1575
+ */
1576
+ async fetch(force = false) {
1081
1577
  return await this.client.channels.fetch(this.id, force);
1082
1578
  }
1083
1579
  /**
1084
1580
  * Fetches multiple messages from this channel.
1085
1581
  * @param options The query parameters to filter the messages.
1582
+ * @throws {Error} If the API request fails
1583
+ * @returns A Collection of Messages, keyed by their ID.
1584
+ * @example
1585
+ * // Fetch the last 50 messages in the channel
1586
+ * const messages = await channel.fetchMessages({ limit: 50 });
1587
+ * console.log(`Fetched ${messages.size} messages`);
1588
+ * // Fetch messages before a specific message ID
1589
+ * const messages = await channel.fetchMessages({ before: "MESSAGE_ID" });
1590
+ * console.log(`Fetched ${messages.size} messages sent before the specified message`);
1591
+ * // Fetch messages after a specific message ID
1592
+ * const messages = await channel.fetchMessages({ after: "MESSAGE_ID" });
1593
+ * console.log(`Fetched ${messages.size} messages sent after the specified message`);
1594
+ * // Fetch messages around a specific message ID
1595
+ * const messages = await channel.fetchMessages({ around: "MESSAGE_ID", limit: 10 });
1596
+ * console.log(`Fetched ${messages.size} messages sent around the specified message`);
1086
1597
  */
1087
1598
  async fetchMessages(options) {
1088
1599
  return this.messages.fetchMany(options);
@@ -1090,16 +1601,72 @@ var BaseChannel = class extends Base {
1090
1601
  /**
1091
1602
  * Edits this channel.
1092
1603
  * @param options The fields to update
1604
+ * @throws {Error} If the API request fails
1605
+ * @returns BaseChannel
1606
+ * @example
1607
+ * // Edit the channel's name
1608
+ * await channel.edit({name: "New Cool Name"});
1093
1609
  */
1094
1610
  async edit(options) {
1095
1611
  return await this.client.channels.edit(this.id, options);
1096
1612
  }
1097
1613
  /**
1098
1614
  * Deletes this channel.
1615
+ * @throws {Error} If the API request fails
1616
+ * @example
1617
+ * // Delete the channel
1618
+ * await channel.delete();
1099
1619
  */
1100
1620
  async delete() {
1101
1621
  await this.client.channels.delete(this.id);
1102
1622
  }
1623
+ /**
1624
+ * Bulk delete messages from this channel
1625
+ * @param messages MessageResolvable to delete
1626
+ * @throws {Error} If the API request fails
1627
+ * @example
1628
+ * // Delete messages by their ID's
1629
+ * await channel.bulkDelete(["MESSAGE_ID_1", "MESSAGE_ID_2", "MESSAGE_ID_3"]);
1630
+ * // Delete messages by their Message objects
1631
+ * await channel.bulkDelete([message1, message2, message3]);
1632
+ */
1633
+ async bulkDelete(messages) {
1634
+ await this.client.channels.bulkDelete(this.id, messages);
1635
+ }
1636
+ /**
1637
+ * Creates a MessageCollector to collect messages in this channel.
1638
+ * @param options The options for the collector.
1639
+ * @returns The instantiated MessageCollector
1640
+ * @example
1641
+ * const collector = channel.createMessageCollector({ filter: m => m.authorId === '123', time: 15000 });
1642
+ * collector.on('collect', m => console.log(`Collected ${m.content}`));
1643
+ * collector.on('end', collected => console.log(`Collected ${collected.size} items`));
1644
+ */
1645
+ createMessageCollector(options) {
1646
+ return new MessageCollector(this, options);
1647
+ }
1648
+ /**
1649
+ * Awaits messages in this channel that meet certain criteria.
1650
+ * @param options The options for the collector.
1651
+ * @returns A promise that resolves to a collection of messages.
1652
+ * @example
1653
+ * // Await !vote messages
1654
+ * const filter = m => m.content.startsWith('!vote');
1655
+ * channel.awaitMessages({ filter, max: 4, time: 60000 })
1656
+ * .then(collected => console.log(collected.size))
1657
+ * .catch(console.error);
1658
+ */
1659
+ awaitMessages(options = {}) {
1660
+ return new Promise((resolve, reject) => {
1661
+ const collector = this.createMessageCollector(options);
1662
+ collector.once("end", (collected, reason) => {
1663
+ if (options.max && reason !== "limit" && reason !== "time") {
1664
+ return reject(new Error(`Collector ended with reason: ${reason}`));
1665
+ }
1666
+ resolve(collected);
1667
+ });
1668
+ });
1669
+ }
1103
1670
  isText() {
1104
1671
  return this.type === "TextChannel" /* TEXT */;
1105
1672
  }
@@ -1143,6 +1710,15 @@ var TextChannel = class extends BaseChannel {
1143
1710
  case "Description":
1144
1711
  this.description = null;
1145
1712
  break;
1713
+ case "Icon":
1714
+ this.icon = null;
1715
+ break;
1716
+ case "DefaultPermissions":
1717
+ this.defaultPermissions = data.default_permissions;
1718
+ break;
1719
+ case "Voice":
1720
+ this.voice = data.voice;
1721
+ break;
1146
1722
  }
1147
1723
  }
1148
1724
  }
@@ -1174,6 +1750,136 @@ var TextChannel = class extends BaseChannel {
1174
1750
  async setDefaultPermissions(permissions) {
1175
1751
  return await this.client.channels.setDefaultPermissions(this.id, permissions);
1176
1752
  }
1753
+ /**
1754
+ * Edits the category of this channel. Only applicable to server channels.
1755
+ * @param category The ID of the category to move this channel into, or "default" to remove from any category.
1756
+ * @returns The updated TextChannel with the new category.
1757
+ * @throws {Error} If the channel is not a server channel, if the category is not found in the server, or if the API request fails.
1758
+ * @example
1759
+ * // Move this channel into a category
1760
+ * await channel.setCategory("CATEGORY_ID");
1761
+ * // Remove this channel from its category
1762
+ * await channel.setCategory("default");
1763
+ */
1764
+ async setCategory(category) {
1765
+ const serverId = this.serverId;
1766
+ const server = await this.client.servers.fetch(serverId);
1767
+ const categories = server.categories.map((c) => ({
1768
+ id: c.id,
1769
+ title: c.title,
1770
+ channels: [...c.channels]
1771
+ }));
1772
+ for (const cat of categories) {
1773
+ cat.channels = cat.channels.filter((id) => id !== this.id);
1774
+ }
1775
+ if (category !== "default") {
1776
+ const targetCategory = categories.find((c) => c.id === category);
1777
+ if (!targetCategory) {
1778
+ throw new Error(`Category ${category} not found in server.`);
1779
+ }
1780
+ targetCategory.channels.push(this.id);
1781
+ }
1782
+ await this.client.servers.edit(serverId, { categories });
1783
+ return this;
1784
+ }
1785
+ /**
1786
+ * Sets the position of this channel within its current category.
1787
+ * @param position The new index position for the channel within its category.
1788
+ * @returns The updated TextChannel.
1789
+ * @throws {Error} If the channel is not in a category, or if the API request fails.
1790
+ * @example
1791
+ * // Move channel to the top of its category
1792
+ * await channel.setPosition(0);
1793
+ */
1794
+ async setPosition(position) {
1795
+ const serverId = this.serverId;
1796
+ const server = await this.client.servers.fetch(serverId);
1797
+ const categories = server.categories.map((c) => ({
1798
+ id: c.id,
1799
+ title: c.title,
1800
+ channels: [...c.channels]
1801
+ }));
1802
+ const currentCategory = categories.find((c) => c.channels.includes(this.id));
1803
+ if (!currentCategory) {
1804
+ throw new Error("This channel is not currently inside any category.");
1805
+ }
1806
+ currentCategory.channels = currentCategory.channels.filter((id) => id !== this.id);
1807
+ const safePosition = Math.max(0, Math.min(position, currentCategory.channels.length));
1808
+ currentCategory.channels.splice(safePosition, 0, this.id);
1809
+ await this.client.servers.edit(serverId, { categories });
1810
+ return this;
1811
+ }
1812
+ /**
1813
+ * Edit the description of this channel
1814
+ * @param description
1815
+ * @throws {Error} If the API request fails
1816
+ * @returns The updated TextChannel
1817
+ * @example
1818
+ * // Set the channel description
1819
+ * await channel.setDescription("This is a channel about cats!");
1820
+ * // Remove the channel description
1821
+ * await channel.setDescription(null);
1822
+ */
1823
+ async setDescription(description) {
1824
+ await this.edit({ description });
1825
+ return this;
1826
+ }
1827
+ /**
1828
+ * Edit the name of this channel
1829
+ * @param name
1830
+ * @throws {Error} If the API request fails
1831
+ * @returns The updated TextChannel
1832
+ * @example
1833
+ * await channel.setName("New Name");
1834
+ */
1835
+ async setName(name) {
1836
+ await this.edit({ name });
1837
+ return this;
1838
+ }
1839
+ /**
1840
+ * Set whether this channel is NSFW
1841
+ * @param nsfw
1842
+ * @throws {Error} If the API request fails
1843
+ * @returns The updated TextChannel
1844
+ * @example
1845
+ * // Mark the channel as NSFW
1846
+ * await channel.setNSFW(true);
1847
+ * // Mark the channel as SFW
1848
+ * await channel.setNSFW(false);
1849
+ */
1850
+ async setNSFW(nsfw) {
1851
+ await this.edit({ nsfw });
1852
+ return this;
1853
+ }
1854
+ /**
1855
+ * Set the channel slowmode in seconds
1856
+ * @param slowmode
1857
+ * @throws {Error} If the API request fails
1858
+ * @returns The updated TextChannel
1859
+ * @example
1860
+ * // Set the slowmode to 5 seconds
1861
+ * await channel.setSlowmode(5);
1862
+ * // Remove slowmode
1863
+ * await channel.setSlowmode(0);
1864
+ */
1865
+ async setSlowmode(slowmode) {
1866
+ await this.edit({ slowmode });
1867
+ return this;
1868
+ }
1869
+ /**
1870
+ * Set the channel Icon
1871
+ * @param id Autumn ID to use
1872
+ * @throws {Error} If the API request fails
1873
+ * @returns The updated TextChannel
1874
+ * @example
1875
+ * await channel.setIcon("123");
1876
+ * // Remove the channel icon
1877
+ * await channel.setIcon(null);
1878
+ */
1879
+ async setIcon(id) {
1880
+ await this.edit({ icon: id });
1881
+ return this;
1882
+ }
1177
1883
  };
1178
1884
 
1179
1885
  // src/structures/UnknownChannel.ts
@@ -1199,7 +1905,7 @@ var DMChannel = class extends BaseChannel {
1199
1905
  };
1200
1906
 
1201
1907
  // src/structures/GroupChannel.ts
1202
- var util3 = __toESM(require("util"), 1);
1908
+ var util4 = __toESM(require("util"), 1);
1203
1909
  var GroupChannel = class extends BaseChannel {
1204
1910
  name;
1205
1911
  ownerId;
@@ -1259,9 +1965,9 @@ var GroupChannel = class extends BaseChannel {
1259
1965
  async setDefaultPermissions(permissions) {
1260
1966
  return await this.client.channels.setDefaultPermissions(this.id, permissions);
1261
1967
  }
1262
- [util3.inspect.custom](_depth, options, inspect10) {
1968
+ [util4.inspect.custom](_depth, options, inspect12) {
1263
1969
  const { client, ...props } = this;
1264
- return `${this.constructor.name} ${inspect10(
1970
+ return `${this.constructor.name} ${inspect12(
1265
1971
  {
1266
1972
  ...props,
1267
1973
  owner: this.owner,
@@ -1412,7 +2118,7 @@ var ChannelManager = class extends BaseManager {
1412
2118
  /**
1413
2119
  * Fetches a Channel from the API or resolves it from the local cache.
1414
2120
  * @param channel The ID, mention, or Channel object to fetch.
1415
- * @param force Whether to skip the cache check and force a direct API request. Defaults to true.
2121
+ * @param force Whether to skip the cache check and force a direct API request. Defaults to false.
1416
2122
  * @returns A promise that resolves to the fetched BaseChannel object.
1417
2123
  * @throws {TypeError} If an invalid ChannelResolvable is provided.
1418
2124
  * @throws {Error} If the API request fails.
@@ -1420,7 +2126,7 @@ var ChannelManager = class extends BaseManager {
1420
2126
  * // Fetch a channel, bypassing cache
1421
2127
  * const channel = await client.channels.fetch("01H...");
1422
2128
  */
1423
- async fetch(channel, force = true) {
2129
+ async fetch(channel, force = false) {
1424
2130
  if (!force) {
1425
2131
  const cached = this.resolve(channel);
1426
2132
  if (cached) return cached;
@@ -1534,10 +2240,51 @@ var ChannelManager = class extends BaseManager {
1534
2240
  await this.client.rest.delete(`/channels/${id}`);
1535
2241
  this.cache.delete(id);
1536
2242
  }
2243
+ /**
2244
+ * Pin a message
2245
+ * @param id Channel ID
2246
+ * @param messageId Message ID
2247
+ * @throws {Error} If the API request fails.
2248
+ * @example
2249
+ * await client.channels.pin("CHANNEL_ID", "MESSAGE_ID");
2250
+ */
2251
+ async pin(id, messageId) {
2252
+ await this.client.rest.post(`/channels/${id}/pins/${messageId}`);
2253
+ }
2254
+ /**
2255
+ * Unpin a message
2256
+ * @param id Channel ID
2257
+ * @param messageId Message ID
2258
+ * @throws {Error} If the API request fails
2259
+ * @example
2260
+ * await client.channels.unpin("CHANNEL_ID", "MESSAGE_ID");
2261
+ */
2262
+ async unpin(id, messageId) {
2263
+ await this.client.rest.delete(`/channels/${id}/pins/${messageId}`);
2264
+ }
2265
+ /**
2266
+ * Bulk delete up to 100 messages
2267
+ * @param id Channel ID
2268
+ * @param messages An array of MessageResolvable
2269
+ * @throws {Error} If the API request fails
2270
+ * @example
2271
+ * await client.channels.bulkDelete("CHANNEL_ID", ["MESSAGE_ID_1", "MESSAGE_ID_2", "MESSAGE_ID_3"]);
2272
+ */
2273
+ async bulkDelete(id, messages) {
2274
+ if (!Array.isArray(messages) || messages.length === 0 || messages.length > 100) {
2275
+ throw new TypeError("Messages must be an array of 1-100 MessageResolvable items.");
2276
+ }
2277
+ const messageIds = messages.map((msg) => {
2278
+ if (typeof msg === "string") return msg.replace(/[<#>]/g, "");
2279
+ if ("id" in msg) return msg.id;
2280
+ throw new TypeError("Invalid MessageResolvable provided. Expected a Message object or a string ID/Mention.");
2281
+ });
2282
+ await this.client.rest.delete(`/channels/${id}/messages/bulk`, { messages: messageIds });
2283
+ }
1537
2284
  };
1538
2285
 
1539
2286
  // src/structures/Member.ts
1540
- var util4 = __toESM(require("util"), 1);
2287
+ var util5 = __toESM(require("util"), 1);
1541
2288
 
1542
2289
  // src/managers/MemberRoleManager.ts
1543
2290
  var MemberRoleManager = class {
@@ -1716,9 +2463,24 @@ var Member = class extends Base {
1716
2463
  * await member.setTimeout(600000);
1717
2464
  */
1718
2465
  async setTimeout(duration) {
1719
- let server = this.server;
1720
- if (!server) server = await this.client.servers.fetch(this.serverId);
1721
- await server.members.setTimeout(this.id, duration);
2466
+ await this.edit({ timeout: new Date(Date.now() + duration).toISOString() });
2467
+ }
2468
+ /**
2469
+ * Send a message to this member.
2470
+ * @param options The content or options for the message to send.
2471
+ * @returns A promise that resolves to the sent Message object.
2472
+ * @throws {Error} If the API request fails.
2473
+ * @example
2474
+ * // Send a message to this member
2475
+ * const message = await member.send("Hello!");
2476
+ * console.log(`Sent message ID: ${message.id}`);
2477
+ */
2478
+ async send(options) {
2479
+ let dmChannel = await this.client.users.createDM(this.id);
2480
+ return dmChannel.messages.send(options);
2481
+ }
2482
+ async setNickname(nickname) {
2483
+ return this.edit({ nickname });
1722
2484
  }
1723
2485
  /** Checks if the member has a specific permission */
1724
2486
  hasPermission(permission) {
@@ -1734,6 +2496,16 @@ var Member = class extends Base {
1734
2496
  if (!server) server = await this.client.servers.fetch(this.serverId);
1735
2497
  return await server.members.edit(this.id, options);
1736
2498
  }
2499
+ /**
2500
+ * When concatenated with a string, this automatically returns the user's mention instead of the GuildMember object.
2501
+ * @returns {string}
2502
+ * @example
2503
+ * // Logs: Hello from <@01JE2MM759J5D7CHJF084R7MJ2>!
2504
+ * console.log(`Hello from ${member}!`);
2505
+ */
2506
+ toString() {
2507
+ return `<@${this.id}>`;
2508
+ }
1737
2509
  /**
1738
2510
  * Kick this member from the server.
1739
2511
  */
@@ -1743,9 +2515,9 @@ var Member = class extends Base {
1743
2515
  await server.members.kick(this.id);
1744
2516
  }
1745
2517
  /** @internal */
1746
- [util4.inspect.custom](depth, options, inspect10) {
2518
+ [util5.inspect.custom](depth, options, inspect12) {
1747
2519
  const { client, serverId, ...props } = this;
1748
- return `${this.constructor.name} ${inspect10(
2520
+ return `${this.constructor.name} ${inspect12(
1749
2521
  {
1750
2522
  ...props,
1751
2523
  user: this.user,
@@ -1757,7 +2529,7 @@ var Member = class extends Base {
1757
2529
  };
1758
2530
 
1759
2531
  // src/managers/MemberManager.ts
1760
- var util5 = __toESM(require("util"), 1);
2532
+ var util6 = __toESM(require("util"), 1);
1761
2533
  var MemberManager = class extends BaseManager {
1762
2534
  constructor(client, server, limit = Infinity) {
1763
2535
  super(client, limit);
@@ -1931,25 +2703,13 @@ var MemberManager = class extends BaseManager {
1931
2703
  const id = this.resolveId(member);
1932
2704
  await this.client.rest.delete(`/servers/${this.server.id}/bans/${id}`);
1933
2705
  }
1934
- /**
1935
- * Timeouts a member in the server for a specified duration.
1936
- * @param member The MemberResolvable to timeout
1937
- * @param duration The duration of the timeout in milliseconds
1938
- * @example
1939
- * // Timeout a member for 10 minutes
1940
- * await server.members.setTimeout("1234567890", 10 * 60 * 1000);
1941
- */
1942
- async setTimeout(member, duration) {
1943
- const id = this.resolveId(member);
1944
- await this.edit(id, { timeout: new Date(Date.now() + duration).toISOString() });
1945
- }
1946
- [util5.inspect.custom]() {
2706
+ [util6.inspect.custom]() {
1947
2707
  return this.cache;
1948
2708
  }
1949
2709
  };
1950
2710
 
1951
2711
  // src/managers/ServerChannelManager.ts
1952
- var util6 = __toESM(require("util"), 1);
2712
+ var util7 = __toESM(require("util"), 1);
1953
2713
  var ServerChannelManager = class {
1954
2714
  client;
1955
2715
  server;
@@ -1979,13 +2739,13 @@ var ServerChannelManager = class {
1979
2739
  const data = await this.client.rest.post(`/servers/${this.server.id}/channels`, payload);
1980
2740
  return this.client.channels._add(data);
1981
2741
  }
1982
- [util6.inspect.custom]() {
2742
+ [util7.inspect.custom]() {
1983
2743
  return this.cache;
1984
2744
  }
1985
2745
  };
1986
2746
 
1987
2747
  // src/structures/Role.ts
1988
- var util7 = __toESM(require("util"), 1);
2748
+ var util8 = __toESM(require("util"), 1);
1989
2749
  var Role = class extends Base {
1990
2750
  serverId;
1991
2751
  name;
@@ -2128,14 +2888,14 @@ var Role = class extends Base {
2128
2888
  * Hides the cyclic client reference and raw serverId for a cleaner output.
2129
2889
  * @internal
2130
2890
  */
2131
- [util7.inspect.custom]() {
2891
+ [util8.inspect.custom]() {
2132
2892
  const { client, serverId, ...props } = this;
2133
- return `${this.constructor.name} ${util7.inspect(props)}`;
2893
+ return `${this.constructor.name} ${util8.inspect(props)}`;
2134
2894
  }
2135
2895
  };
2136
2896
 
2137
2897
  // src/managers/RoleManager.ts
2138
- var util8 = __toESM(require("util"), 1);
2898
+ var util9 = __toESM(require("util"), 1);
2139
2899
  var RoleManager = class extends BaseManager {
2140
2900
  /**
2141
2901
  * Manages API methods and caching for server roles.
@@ -2174,7 +2934,7 @@ var RoleManager = class extends BaseManager {
2174
2934
  this.cache.set(role.id, role);
2175
2935
  return role;
2176
2936
  }
2177
- [util8.inspect.custom]() {
2937
+ [util9.inspect.custom]() {
2178
2938
  return this.cache;
2179
2939
  }
2180
2940
  /**
@@ -2475,6 +3235,54 @@ var ServerBanManager = class extends BaseManager {
2475
3235
  }
2476
3236
  };
2477
3237
 
3238
+ // src/structures/Emoji.ts
3239
+ var Emoji = class extends Base {
3240
+ creatorId;
3241
+ name;
3242
+ parent;
3243
+ animated = false;
3244
+ nsfw = false;
3245
+ constructor(client, data) {
3246
+ super(client, data);
3247
+ this._patch(data);
3248
+ }
3249
+ _patch(data) {
3250
+ if (data.creator_id !== void 0) this.creatorId = data.creator_id;
3251
+ if (data.name !== void 0) this.name = data.name;
3252
+ if (data.parent !== void 0) this.parent = data.parent;
3253
+ if (data.animated !== void 0) this.animated = data.animated;
3254
+ if (data.nsfw !== void 0) this.nsfw = data.nsfw;
3255
+ }
3256
+ };
3257
+
3258
+ // src/managers/EmojiManager.ts
3259
+ var util10 = __toESM(require("util"), 1);
3260
+ var EmojiManager = class extends BaseManager {
3261
+ constructor(client, server, limit = Infinity) {
3262
+ super(client, limit);
3263
+ this.server = server;
3264
+ }
3265
+ /**
3266
+ * Tell BaseManager how to find the ID for Emojis
3267
+ */
3268
+ extractId(data) {
3269
+ return data._id ?? data.id;
3270
+ }
3271
+ /**
3272
+ * Tell BaseManager how to build an Emoji
3273
+ */
3274
+ construct(data) {
3275
+ return new Emoji(this.client, data);
3276
+ }
3277
+ async fetch(id) {
3278
+ const data = await this.client.rest.get(`/custom/emoji/${id}`);
3279
+ return this._add(data);
3280
+ }
3281
+ [util10.inspect.custom]() {
3282
+ return this.cache;
3283
+ }
3284
+ };
3285
+
2478
3286
  // src/structures/Server.ts
2479
3287
  var Server = class extends Base {
2480
3288
  channelIds = [];
@@ -2494,6 +3302,7 @@ var Server = class extends Base {
2494
3302
  roles;
2495
3303
  bans;
2496
3304
  invites;
3305
+ emojis;
2497
3306
  constructor(client, data) {
2498
3307
  super(client, data);
2499
3308
  this.channels = new ServerChannelManager(client, this);
@@ -2501,6 +3310,7 @@ var Server = class extends Base {
2501
3310
  this.roles = new RoleManager(client, this);
2502
3311
  this.bans = new ServerBanManager(this.client, this);
2503
3312
  this.invites = new ServerInviteManager(this.client, this);
3313
+ this.emojis = new EmojiManager(this.client, this);
2504
3314
  this._patch(data);
2505
3315
  }
2506
3316
  /**
@@ -2534,6 +3344,13 @@ var Server = class extends Base {
2534
3344
  this.roles._add({ id, ...roleData });
2535
3345
  }
2536
3346
  }
3347
+ if (data.emojis !== void 0) {
3348
+ if (Array.isArray(data.emojis)) {
3349
+ for (const emoji of data.emojis) {
3350
+ this.emojis._add(emoji);
3351
+ }
3352
+ }
3353
+ }
2537
3354
  if (clear && Array.isArray(clear)) {
2538
3355
  for (const field of clear) {
2539
3356
  switch (field) {
@@ -2572,7 +3389,7 @@ var Server = class extends Base {
2572
3389
  };
2573
3390
 
2574
3391
  // src/managers/ServerManager.ts
2575
- var util9 = __toESM(require("util"), 1);
3392
+ var util11 = __toESM(require("util"), 1);
2576
3393
  var ServerManager = class extends BaseManager {
2577
3394
  constructor(client, limit = Infinity) {
2578
3395
  super(client, limit);
@@ -2645,7 +3462,7 @@ var ServerManager = class extends BaseManager {
2645
3462
  const data = await this.client.rest.patch(`/servers/${serverId}`, payload);
2646
3463
  return this._add(data);
2647
3464
  }
2648
- [util9.inspect.custom]() {
3465
+ [util11.inspect.custom]() {
2649
3466
  return this.cache;
2650
3467
  }
2651
3468
  };
@@ -2874,7 +3691,7 @@ var SweeperManager = class {
2874
3691
  };
2875
3692
 
2876
3693
  // src/client/Client.ts
2877
- var Client = class extends import_events.EventEmitter {
3694
+ var Client = class extends import_events2.EventEmitter {
2878
3695
  constructor(options = {}) {
2879
3696
  super({ captureRejections: true });
2880
3697
  this.options = options;
@@ -2883,6 +3700,7 @@ var Client = class extends import_events.EventEmitter {
2883
3700
  this.channels = new ChannelManager(this, options.cacheLimits?.channels);
2884
3701
  this.servers = new ServerManager(this, options.cacheLimits?.servers);
2885
3702
  this.users = new UserManager(this, options.cacheLimits?.users);
3703
+ this.emojis = new EmojiManager(this, void 0, options.cacheLimits?.emojis);
2886
3704
  this.sweepers = new SweeperManager(this, options.sweepers ?? {});
2887
3705
  }
2888
3706
  rest;
@@ -2891,6 +3709,7 @@ var Client = class extends import_events.EventEmitter {
2891
3709
  servers;
2892
3710
  users;
2893
3711
  sweepers;
3712
+ emojis;
2894
3713
  user = null;
2895
3714
  /**
2896
3715
  * Connects the bot to the Stoat Gateway
@@ -2962,16 +3781,22 @@ var EmbedBuilder = class {
2962
3781
  Client,
2963
3782
  ClientUser,
2964
3783
  Collection,
3784
+ Collector,
2965
3785
  DMChannel,
2966
3786
  EmbedBuilder,
3787
+ Emoji,
3788
+ EmojiManager,
2967
3789
  GatewayManager,
2968
3790
  Member,
2969
3791
  MemberManager,
2970
3792
  Message,
3793
+ MessageCollector,
2971
3794
  MessageManager,
3795
+ MessageReaction,
2972
3796
  PermissionFlags,
2973
3797
  Permissions,
2974
3798
  RESTManager,
3799
+ ReactionCollector,
2975
3800
  Role,
2976
3801
  RoleManager,
2977
3802
  Server,