@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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/client/Client.ts
2
- import { EventEmitter } from "events";
2
+ import { EventEmitter as EventEmitter2 } from "events";
3
3
 
4
4
  // src/gateway/GatewayManager.ts
5
5
  import WebSocket from "ws";
@@ -40,7 +40,7 @@ var Base = class _Base {
40
40
  };
41
41
 
42
42
  // src/structures/Message.ts
43
- import * as util from "util";
43
+ import * as util2 from "util";
44
44
 
45
45
  // src/structures/Attachment.ts
46
46
  var Attachment = class extends Base {
@@ -87,6 +87,306 @@ var Attachment = class extends Base {
87
87
 
88
88
  // src/structures/Message.ts
89
89
  import { decodeTime } from "ulid";
90
+
91
+ // src/utils/Collector.ts
92
+ import { EventEmitter } from "events";
93
+
94
+ // src/utils/Collection.ts
95
+ var Collection = class _Collection extends Map {
96
+ limit;
97
+ constructor(limit = Infinity) {
98
+ super();
99
+ this.limit = limit;
100
+ }
101
+ /**
102
+ * Overrides the default set method to enforce the maximum cache size.
103
+ */
104
+ set(key, value) {
105
+ if (this.limit === 0) return this;
106
+ if (this.size >= this.limit && !this.has(key)) {
107
+ const oldestKey = this.keys().next().value;
108
+ if (oldestKey !== void 0) {
109
+ this.delete(oldestKey);
110
+ }
111
+ }
112
+ return super.set(key, value);
113
+ }
114
+ /**
115
+ * Finds the first item where the given function returns true.
116
+ */
117
+ find(fn) {
118
+ for (const [key, val] of this) {
119
+ if (fn(val, key, this)) return val;
120
+ }
121
+ return void 0;
122
+ }
123
+ /**
124
+ * Returns a new Collection containing only the items where the function returns true.
125
+ */
126
+ filter(fn) {
127
+ const results = new _Collection();
128
+ for (const [key, val] of this) {
129
+ if (fn(val, key, this)) results.set(key, val);
130
+ }
131
+ return results;
132
+ }
133
+ /**
134
+ * Maps each item to a new array of values.
135
+ */
136
+ map(fn) {
137
+ const results = [];
138
+ for (const [key, val] of this) {
139
+ results.push(fn(val, key, this));
140
+ }
141
+ return results;
142
+ }
143
+ /**
144
+ * Gets the very first value in the Collection (based on insertion order).
145
+ */
146
+ first() {
147
+ return this.values().next().value;
148
+ }
149
+ /**
150
+ * Gets the very last value in the Collection.
151
+ */
152
+ last() {
153
+ const arr = Array.from(this.values());
154
+ return arr[arr.length - 1];
155
+ }
156
+ /**
157
+ * Checks if at least one item matches the condition.
158
+ */
159
+ some(fn) {
160
+ for (const [key, val] of this) {
161
+ if (fn(val, key, this)) return true;
162
+ }
163
+ return false;
164
+ }
165
+ };
166
+
167
+ // src/utils/Collector.ts
168
+ var Collector = class extends EventEmitter {
169
+ client;
170
+ filter;
171
+ options;
172
+ collected;
173
+ ended = false;
174
+ _timeout = null;
175
+ _idletimeout = null;
176
+ constructor(client, options = {}) {
177
+ super();
178
+ this.client = client;
179
+ this.options = options;
180
+ this.filter = options.filter ?? (() => true);
181
+ this.collected = new Collection();
182
+ if (options.time) {
183
+ this._timeout = setTimeout(() => this.stop("time"), options.time);
184
+ }
185
+ if (options.idle) {
186
+ this._idletimeout = setTimeout(() => this.stop("idle"), options.idle);
187
+ }
188
+ }
189
+ /**
190
+ * Evaluates an item and possibly passes it to the collector
191
+ */
192
+ handleCollect(item, ...args) {
193
+ if (this.ended) return;
194
+ if (!this.filter(item, ...args)) return;
195
+ const key = this.collect(item, ...args);
196
+ if (key !== null && key !== void 0) {
197
+ this.collected.set(key, item);
198
+ this.emit("collect", item, ...args);
199
+ if (this._idletimeout) {
200
+ clearTimeout(this._idletimeout);
201
+ this._idletimeout = setTimeout(() => this.stop("idle"), this.options.idle);
202
+ }
203
+ this.checkEnd();
204
+ }
205
+ }
206
+ /**
207
+ * Evaluates an item and possibly removes it from the collector
208
+ */
209
+ handleDispose(item, ...args) {
210
+ if (this.ended) return;
211
+ if (!this.options.dispose) return;
212
+ const key = this.dispose(item, ...args);
213
+ if (key !== null && key !== void 0) {
214
+ this.collected.delete(key);
215
+ this.emit("dispose", item, ...args);
216
+ this.checkEnd();
217
+ }
218
+ }
219
+ /**
220
+ * Stops the collector.
221
+ */
222
+ stop(reason = "user") {
223
+ if (this.ended) return;
224
+ this.ended = true;
225
+ if (this._timeout) clearTimeout(this._timeout);
226
+ if (this._idletimeout) clearTimeout(this._idletimeout);
227
+ this.removeAllListeners("collect");
228
+ this.removeAllListeners("dispose");
229
+ this.emit("end", this.collected, reason);
230
+ }
231
+ /**
232
+ * Check if we should end upon collecting/disposing
233
+ */
234
+ checkEnd() {
235
+ const reason = this.endReason();
236
+ if (reason) this.stop(reason);
237
+ }
238
+ /**
239
+ * Check if there's a reason to end
240
+ */
241
+ endReason() {
242
+ return null;
243
+ }
244
+ /**
245
+ * Allows iterating over collected items asynchronously.
246
+ * @example
247
+ * for await (const [id, message] of collector) {
248
+ * console.log(`Received message: ${message.content}`);
249
+ * }
250
+ */
251
+ async *[Symbol.asyncIterator]() {
252
+ const queue = [];
253
+ let resolve = null;
254
+ const onCollect = (item, ...args) => {
255
+ const key = this.collect(item, ...args);
256
+ if (key !== null && key !== void 0) {
257
+ queue.push([key, item]);
258
+ }
259
+ if (resolve) {
260
+ resolve();
261
+ resolve = null;
262
+ }
263
+ };
264
+ const onEnd = () => {
265
+ if (resolve) {
266
+ resolve();
267
+ resolve = null;
268
+ }
269
+ };
270
+ this.on("collect", onCollect);
271
+ this.on("end", onEnd);
272
+ try {
273
+ while (true) {
274
+ if (queue.length > 0) {
275
+ yield queue.shift();
276
+ } else if (this.ended) {
277
+ break;
278
+ } else {
279
+ await new Promise((res) => {
280
+ resolve = res;
281
+ });
282
+ }
283
+ }
284
+ } finally {
285
+ this.removeListener("collect", onCollect);
286
+ this.removeListener("end", onEnd);
287
+ }
288
+ }
289
+ };
290
+
291
+ // src/structures/MessageReaction.ts
292
+ import * as util from "util";
293
+ var MessageReaction = class {
294
+ constructor(client, data) {
295
+ this.client = client;
296
+ this.message = data.message;
297
+ this.emoji = this.client.emojis.cache.get(data.emojiId) || data.emojiId;
298
+ this.users = new Collection();
299
+ if (data.users) {
300
+ for (const userId of data.users) {
301
+ const user = this.client.users.cache.get(userId) || { id: userId };
302
+ this.users.set(userId, user);
303
+ }
304
+ }
305
+ }
306
+ message;
307
+ emoji;
308
+ users;
309
+ get count() {
310
+ return this.users.size;
311
+ }
312
+ async remove() {
313
+ if (this.message instanceof Message) {
314
+ const emojiId = typeof this.emoji === "string" ? this.emoji : this.emoji.id;
315
+ await this.message.removeReaction(emojiId);
316
+ }
317
+ }
318
+ [util.inspect.custom]() {
319
+ const data = {
320
+ messageId: this.message.id,
321
+ emoji: this.emoji,
322
+ count: this.count,
323
+ users: Array.from(this.users.keys())
324
+ };
325
+ return `MessageReaction ${util.inspect(data)}`;
326
+ }
327
+ };
328
+
329
+ // src/utils/ReactionCollector.ts
330
+ var ReactionCollector = class extends Collector {
331
+ constructor(message, options = {}) {
332
+ super(message.client, options);
333
+ this.message = message;
334
+ this.messageId = message.id;
335
+ const boundHandleCollect = this.handleMessageReact.bind(this);
336
+ const boundHandleDispose = this.handleMessageUnreact.bind(this);
337
+ this.client.on("messageReact", boundHandleCollect);
338
+ this.client.on("messageUnreact", boundHandleDispose);
339
+ this.once("end", () => {
340
+ this.client.removeListener("messageReact", boundHandleCollect);
341
+ this.client.removeListener("messageUnreact", boundHandleDispose);
342
+ });
343
+ }
344
+ messageId;
345
+ total = 0;
346
+ users = /* @__PURE__ */ new Set();
347
+ collect(reaction) {
348
+ if (reaction.message.id !== this.messageId) return null;
349
+ return typeof reaction.emoji === "string" ? reaction.emoji : reaction.emoji.id;
350
+ }
351
+ dispose(reaction) {
352
+ if (reaction.message.id !== this.messageId) return null;
353
+ return typeof reaction.emoji === "string" ? reaction.emoji : reaction.emoji.id;
354
+ }
355
+ handleMessageReact(message, emojiId, userId) {
356
+ if (message.id !== this.messageId) return;
357
+ let reaction = this.collected.get(emojiId);
358
+ if (!reaction) {
359
+ reaction = new MessageReaction(this.client, { message, emojiId, users: [userId] });
360
+ } else {
361
+ const user = this.client.users.cache.get(userId) || { id: userId };
362
+ reaction.users.set(userId, user);
363
+ }
364
+ super.handleCollect(reaction);
365
+ if (!this.ended && this.collected.has(emojiId)) {
366
+ this.total++;
367
+ this.users.add(userId);
368
+ this.checkEnd();
369
+ }
370
+ }
371
+ handleMessageUnreact(message, emojiId, userId) {
372
+ if (message.id !== this.messageId) return;
373
+ const reaction = this.collected.get(emojiId);
374
+ if (reaction) {
375
+ reaction.users.delete(userId);
376
+ if (reaction.users.size === 0) {
377
+ super.handleDispose(reaction);
378
+ }
379
+ }
380
+ }
381
+ endReason() {
382
+ const options = this.options;
383
+ if (options.max && this.total >= options.max) return "limit";
384
+ if (options.maxUsers && this.users.size >= options.maxUsers) return "userLimit";
385
+ return null;
386
+ }
387
+ };
388
+
389
+ // src/structures/Message.ts
90
390
  var Message = class extends Base {
91
391
  content = null;
92
392
  authorId;
@@ -100,7 +400,7 @@ var Message = class extends Base {
100
400
  masquerade = null;
101
401
  mentions = [];
102
402
  pinned = false;
103
- reactions = [];
403
+ reactions = {};
104
404
  replies = [];
105
405
  role_mentions = [];
106
406
  constructor(client, data) {
@@ -168,6 +468,78 @@ var Message = class extends Base {
168
468
  if (!channel) channel = await this.client.channels.fetch(this.channelId);
169
469
  await channel.messages.unpin(this.id);
170
470
  }
471
+ /**
472
+ * React to this message
473
+ * @param reaction The emoji to react with. Can be a Unicode emoji or a custom emoji ID.
474
+ * @throws {Error} If the API request fails.
475
+ * @example
476
+ * await message.react("👍");
477
+ * await message.react("customEmojiId");
478
+ */
479
+ async react(reaction) {
480
+ let channel = this.channel;
481
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
482
+ await channel.messages.react(this.id, reaction);
483
+ }
484
+ /**
485
+ * Remove a reaction from this message
486
+ * @param reaction The emoji to remove. Can be a Unicode emoji or a custom emoji ID.
487
+ * @param userId The ID of the user whose reaction to remove. If not provided, removes the current user's reaction.
488
+ * @param removeAll Remove all reactions of this type.
489
+ * @throws {Error} If both userId and removeAll are provided, or if the API request fails.
490
+ * @example
491
+ * // Remove the current user's reaction
492
+ * await message.removeReaction("👍");
493
+ * // Remove a specific user's reaction
494
+ * await message.removeReaction("👍", userId);
495
+ * // Remove all reactions of this type
496
+ * await message.removeReaction("👍", undefined, true);
497
+ */
498
+ async removeReaction(reaction, userId, removeAll) {
499
+ let channel = this.channel;
500
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
501
+ await channel.messages.removeReaction(this.id, reaction, userId, removeAll);
502
+ }
503
+ /**
504
+ * Remove all reactions from this message
505
+ * @throws {Error} If the API request fails.
506
+ * @example
507
+ * await message.clearReactions();
508
+ */
509
+ async clearReactions() {
510
+ let channel = this.channel;
511
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
512
+ await channel.messages.clearReactions(this.id);
513
+ }
514
+ /**
515
+ * Creates a ReactionCollector to collect reactions on this message.
516
+ * @param options The options for the collector.
517
+ * @returns A new ReactionCollector instance.
518
+ * @example
519
+ * const collector = message.createReactionCollector({ time: 15000 });
520
+ * collector.on('collect', (reaction) => console.log(`Collected ${reaction.emojiId} from ${reaction.userId}`));
521
+ * collector.on('end', (collected) => console.log(`Collected ${collected.size} items`));
522
+ */
523
+ createReactionCollector(options) {
524
+ return new ReactionCollector(this, options);
525
+ }
526
+ /**
527
+ * Awaits reactions on this message.
528
+ * @param options The options for the collector.
529
+ * @returns A promise that resolves to a collection of reactions collected.
530
+ * @example
531
+ * // Await reactions
532
+ * const filter = (reaction) => reaction.emoji.id === '123' && reaction.users.has(author.id);
533
+ * message.awaitReactions({ filter, max: 1, time: 60000 })
534
+ * .then(collected => console.log(collected.size))
535
+ * .catch(console.error);
536
+ */
537
+ awaitReactions(options) {
538
+ return new Promise((resolve) => {
539
+ const collector = this.createReactionCollector(options);
540
+ collector.once("end", (collected) => resolve(collected));
541
+ });
542
+ }
171
543
  /** Gets the Channel object from cache */
172
544
  get channel() {
173
545
  return this.client.channels.cache.get(this.channelId);
@@ -205,7 +577,9 @@ var Message = class extends Base {
205
577
  if (data.pinned !== void 0) this.pinned = data.pinned;
206
578
  if (data.embeds !== void 0) this.embeds = data.embeds;
207
579
  if (data.flags !== void 0) this.flags = data.flags;
208
- if (data.reactions !== void 0) this.reactions = data.reactions;
580
+ if (data.reactions !== void 0) {
581
+ this.reactions = Array.isArray(data.reactions) ? {} : data.reactions;
582
+ }
209
583
  if (data.interactions !== void 0) {
210
584
  if (data.interactions) {
211
585
  this.interactions = {
@@ -218,7 +592,7 @@ var Message = class extends Base {
218
592
  }
219
593
  }
220
594
  // This tells Node.js exactly how to print this object in console.log()
221
- [util.inspect.custom](depth, options, inspect10) {
595
+ [util2.inspect.custom](depth, options, inspect12) {
222
596
  const { client, authorId, channelId, ...props } = this;
223
597
  const data = {
224
598
  ...props,
@@ -227,7 +601,7 @@ var Message = class extends Base {
227
601
  server: this.server,
228
602
  member: this.member
229
603
  };
230
- return `${this.constructor.name} ${inspect10(data, { ...options, depth: depth ?? options.depth })}`;
604
+ return `${this.constructor.name} ${inspect12(data, { ...options, depth: depth ?? options.depth })}`;
231
605
  }
232
606
  };
233
607
 
@@ -389,6 +763,17 @@ var GatewayManager = class {
389
763
  }
390
764
  }
391
765
  }
766
+ if (payload.emojis) {
767
+ for (const rawEmoji of payload.emojis) {
768
+ const emoji = this.client.emojis._add(rawEmoji);
769
+ if (rawEmoji.parent && rawEmoji.parent.type === "Server") {
770
+ const server = this.client.servers.cache.get(rawEmoji.parent.id);
771
+ if (server) {
772
+ server.emojis._add(emoji);
773
+ }
774
+ }
775
+ }
776
+ }
392
777
  this.client.emit("ready", payload);
393
778
  break;
394
779
  }
@@ -448,6 +833,60 @@ var GatewayManager = class {
448
833
  }
449
834
  break;
450
835
  }
836
+ case "MessageReact": {
837
+ const channel = this.client.channels.cache.get(payload.channel_id);
838
+ const message = channel?.messages.cache.get(payload.id);
839
+ if (message) {
840
+ if (!message.reactions) message.reactions = {};
841
+ if (!message.reactions[payload.emoji_id]) {
842
+ message.reactions[payload.emoji_id] = [];
843
+ }
844
+ const reactions = message.reactions[payload.emoji_id];
845
+ if (reactions && !reactions.includes(payload.user_id)) {
846
+ reactions.push(payload.user_id);
847
+ }
848
+ }
849
+ this.client.emit(
850
+ "messageReact",
851
+ message || { id: payload.id, channelId: payload.channel_id },
852
+ payload.emoji_id,
853
+ payload.user_id
854
+ );
855
+ break;
856
+ }
857
+ case "MessageUnreact": {
858
+ const channel = this.client.channels.cache.get(payload.channel_id);
859
+ const message = channel?.messages.cache.get(payload.id);
860
+ if (message && message.reactions && message.reactions[payload.emoji_id]) {
861
+ const reactions = message.reactions[payload.emoji_id];
862
+ if (reactions) {
863
+ message.reactions[payload.emoji_id] = reactions.filter((userId) => userId !== payload.user_id);
864
+ if (message.reactions[payload.emoji_id].length === 0) {
865
+ delete message.reactions[payload.emoji_id];
866
+ }
867
+ }
868
+ }
869
+ this.client.emit(
870
+ "messageUnreact",
871
+ message || { id: payload.id, channelId: payload.channel_id },
872
+ payload.emoji_id,
873
+ payload.user_id
874
+ );
875
+ break;
876
+ }
877
+ case "MessageRemoveReaction": {
878
+ const channel = this.client.channels.cache.get(payload.channel_id);
879
+ const message = channel?.messages.cache.get(payload.id);
880
+ if (message && message.reactions) {
881
+ delete message.reactions[payload.emoji_id];
882
+ }
883
+ this.client.emit(
884
+ "messageRemoveReaction",
885
+ message || { id: payload.id, channelId: payload.channel_id },
886
+ payload.emoji_id
887
+ );
888
+ break;
889
+ }
451
890
  case "Pong":
452
891
  this.client.emit("debug", "Received Pong from server.");
453
892
  break;
@@ -524,6 +963,27 @@ var GatewayManager = class {
524
963
  }
525
964
  break;
526
965
  }
966
+ case "EmojiCreate": {
967
+ const emoji = this.client.emojis._add(payload);
968
+ if (payload.parent?.type === "Server") {
969
+ const server = this.client.servers.cache.get(payload.parent.id);
970
+ if (server) {
971
+ server.emojis._add(emoji);
972
+ }
973
+ }
974
+ break;
975
+ }
976
+ case "EmojiDelete": {
977
+ this.client.emojis.cache.delete(payload.id);
978
+ for (const server of this.client.servers.cache.values()) {
979
+ const emoji = server.emojis.cache.get(payload.id);
980
+ if (emoji) {
981
+ server.emojis.cache.delete(payload.id);
982
+ break;
983
+ }
984
+ }
985
+ break;
986
+ }
527
987
  case "UserUpdate": {
528
988
  const existing = this.client.users.cache.get(payload.id);
529
989
  if (existing) {
@@ -742,89 +1202,16 @@ var RESTManager = class {
742
1202
  patch(endpoint, body) {
743
1203
  return this.makeRequest("PATCH", endpoint, body);
744
1204
  }
745
- delete(endpoint) {
746
- return this.makeRequest("DELETE", endpoint);
1205
+ delete(endpoint, body) {
1206
+ return this.makeRequest("DELETE", endpoint, body);
747
1207
  }
748
1208
  async put(endpoint, body) {
749
1209
  return this.makeRequest("PUT", endpoint, body);
750
1210
  }
751
1211
  };
752
1212
 
753
- // src/utils/Collection.ts
754
- var Collection = class _Collection extends Map {
755
- limit;
756
- constructor(limit = Infinity) {
757
- super();
758
- this.limit = limit;
759
- }
760
- /**
761
- * Overrides the default set method to enforce the maximum cache size.
762
- */
763
- set(key, value) {
764
- if (this.limit === 0) return this;
765
- if (this.size >= this.limit && !this.has(key)) {
766
- const oldestKey = this.keys().next().value;
767
- if (oldestKey !== void 0) {
768
- this.delete(oldestKey);
769
- }
770
- }
771
- return super.set(key, value);
772
- }
773
- /**
774
- * Finds the first item where the given function returns true.
775
- */
776
- find(fn) {
777
- for (const [key, val] of this) {
778
- if (fn(val, key, this)) return val;
779
- }
780
- return void 0;
781
- }
782
- /**
783
- * Returns a new Collection containing only the items where the function returns true.
784
- */
785
- filter(fn) {
786
- const results = new _Collection();
787
- for (const [key, val] of this) {
788
- if (fn(val, key, this)) results.set(key, val);
789
- }
790
- return results;
791
- }
792
- /**
793
- * Maps each item to a new array of values.
794
- */
795
- map(fn) {
796
- const results = [];
797
- for (const [key, val] of this) {
798
- results.push(fn(val, key, this));
799
- }
800
- return results;
801
- }
802
- /**
803
- * Gets the very first value in the Collection (based on insertion order).
804
- */
805
- first() {
806
- return this.values().next().value;
807
- }
808
- /**
809
- * Gets the very last value in the Collection.
810
- */
811
- last() {
812
- const arr = Array.from(this.values());
813
- return arr[arr.length - 1];
814
- }
815
- /**
816
- * Checks if at least one item matches the condition.
817
- */
818
- some(fn) {
819
- for (const [key, val] of this) {
820
- if (fn(val, key, this)) return true;
821
- }
822
- return false;
823
- }
824
- };
825
-
826
1213
  // src/managers/MessageManager.ts
827
- import * as util2 from "util";
1214
+ import * as util3 from "util";
828
1215
 
829
1216
  // src/managers/BaseManager.ts
830
1217
  var BaseManager = class {
@@ -980,11 +1367,105 @@ var MessageManager = class extends BaseManager {
980
1367
  const existing = this.cache.get(id);
981
1368
  if (existing) existing.pinned = false;
982
1369
  }
983
- [util2.inspect.custom]() {
1370
+ /**
1371
+ * React to a message
1372
+ * @param message The MessageResolvable to react to.
1373
+ * @param reaction The emoji to react with. Can be a Unicode emoji or a custom emoji ID.
1374
+ * @throws {Error} If the API request fails.
1375
+ * @example
1376
+ * await channel.messages.react(messageId, "👍");
1377
+ * await channel.messages.react(messageId, "customEmojiId");
1378
+ */
1379
+ async react(message, reaction) {
1380
+ const id = this.resolveId(message);
1381
+ await this.client.rest.put(`/channels/${this.channel.id}/messages/${id}/reactions/${encodeURIComponent(reaction)}`);
1382
+ }
1383
+ /**
1384
+ * Remove a reaction(s) from a message
1385
+ * Requires ManageMessages if changing others' reactions.
1386
+ * @param reaction The emoji to remove. Can be a unicode emoji or a custom emoji ID.
1387
+ * @param message The MessageResolvable to remove the reaction from.
1388
+ * @param userId The ID of the user whose reaction to remove. If not provided, removes the current user's reaction.
1389
+ * @param removeAll Remove all reactions of this type.
1390
+ * @throws {Error} If both userId and removeAll are provided, or if the API request fails.
1391
+ * @example
1392
+ * // Remove the current user's reaction
1393
+ * await channel.messages.removeReaction(messageId, "👍");
1394
+ * // Remove a specific user's reaction
1395
+ * await channel.messages.removeReaction(messageId, "👍", userId);
1396
+ * // Remove all reactions of this type
1397
+ * await channel.messages.removeReaction(messageId, "👍", undefined, true);
1398
+ */
1399
+ async removeReaction(message, reaction, userId, removeAll) {
1400
+ const id = this.resolveId(message);
1401
+ const targetUser = userId ? this.client.users.resolveId(userId) : void 0;
1402
+ const params = new URLSearchParams();
1403
+ if (targetUser) params.append("user_id", targetUser);
1404
+ if (removeAll) params.append("remove_all", "true");
1405
+ const queryString = params.toString();
1406
+ const endpoint = `/channels/${this.channel.id}/messages/${id}/reactions/${encodeURIComponent(reaction)}${queryString ? `?${queryString}` : ""}`;
1407
+ await this.client.rest.delete(endpoint);
1408
+ }
1409
+ /**
1410
+ * Remove all reactions from a message
1411
+ * Requires ManageMessages permission.
1412
+ * @param message The MessageResolvable to clear reactions from.
1413
+ * @throws {Error} If the API request fails.
1414
+ * @example
1415
+ * await channel.messages.clearReactions(messageId);
1416
+ */
1417
+ async clearReactions(message) {
1418
+ const id = this.resolveId(message);
1419
+ await this.client.rest.delete(`/channels/${this.channel.id}/messages/${id}/reactions`);
1420
+ }
1421
+ [util3.inspect.custom]() {
984
1422
  return this.cache;
985
1423
  }
986
1424
  };
987
1425
 
1426
+ // src/utils/MessageCollector.ts
1427
+ var MessageCollector = class extends Collector {
1428
+ constructor(channel, options = {}) {
1429
+ super(channel.client, options);
1430
+ this.channel = channel;
1431
+ this.channelId = channel.id;
1432
+ const boundHandleCollect = this.handleCollect.bind(this);
1433
+ const boundHandleDispose = this.handleDispose.bind(this);
1434
+ this.client.on("messageCreate", boundHandleCollect);
1435
+ this.client.on("messageDelete", boundHandleDispose);
1436
+ this.once("end", () => {
1437
+ this.client.removeListener("messageCreate", boundHandleCollect);
1438
+ this.client.removeListener("messageDelete", boundHandleDispose);
1439
+ });
1440
+ }
1441
+ channelId;
1442
+ total = 0;
1443
+ processed = 0;
1444
+ collect(message) {
1445
+ if (message.channelId !== this.channelId) return null;
1446
+ return message.id;
1447
+ }
1448
+ dispose(message) {
1449
+ if (message.channelId !== this.channelId) return null;
1450
+ return message.id;
1451
+ }
1452
+ handleCollect(message) {
1453
+ if (message.channelId !== this.channelId) return;
1454
+ this.processed++;
1455
+ super.handleCollect(message);
1456
+ if (!this.ended && this.collected.has(message.id)) {
1457
+ this.total++;
1458
+ this.checkEnd();
1459
+ }
1460
+ }
1461
+ endReason() {
1462
+ const options = this.options;
1463
+ if (options.max && this.total >= options.max) return "limit";
1464
+ if (options.maxProcessed && this.processed >= options.maxProcessed) return "processedLimit";
1465
+ return null;
1466
+ }
1467
+ };
1468
+
988
1469
  // src/structures/BaseChannel.ts
989
1470
  var ChannelType = /* @__PURE__ */ ((ChannelType2) => {
990
1471
  ChannelType2["TEXT"] = "TextChannel";
@@ -1011,12 +1492,36 @@ var BaseChannel = class extends Base {
1011
1492
  async send(contentOrOptions) {
1012
1493
  return this.messages.send(contentOrOptions);
1013
1494
  }
1014
- async fetch(force = true) {
1495
+ /**
1496
+ * Fetch this channel
1497
+ * @param force Whether to skip the cache check and force a direct API request. Defaults to false
1498
+ * @throws {Error} If the API request fails
1499
+ * @returns {BaseChannel}
1500
+ * @example
1501
+ * // Force fetch channel to update its data
1502
+ * await channel.fetch(true);
1503
+ */
1504
+ async fetch(force = false) {
1015
1505
  return await this.client.channels.fetch(this.id, force);
1016
1506
  }
1017
1507
  /**
1018
1508
  * Fetches multiple messages from this channel.
1019
1509
  * @param options The query parameters to filter the messages.
1510
+ * @throws {Error} If the API request fails
1511
+ * @returns A Collection of Messages, keyed by their ID.
1512
+ * @example
1513
+ * // Fetch the last 50 messages in the channel
1514
+ * const messages = await channel.fetchMessages({ limit: 50 });
1515
+ * console.log(`Fetched ${messages.size} messages`);
1516
+ * // Fetch messages before a specific message ID
1517
+ * const messages = await channel.fetchMessages({ before: "MESSAGE_ID" });
1518
+ * console.log(`Fetched ${messages.size} messages sent before the specified message`);
1519
+ * // Fetch messages after a specific message ID
1520
+ * const messages = await channel.fetchMessages({ after: "MESSAGE_ID" });
1521
+ * console.log(`Fetched ${messages.size} messages sent after the specified message`);
1522
+ * // Fetch messages around a specific message ID
1523
+ * const messages = await channel.fetchMessages({ around: "MESSAGE_ID", limit: 10 });
1524
+ * console.log(`Fetched ${messages.size} messages sent around the specified message`);
1020
1525
  */
1021
1526
  async fetchMessages(options) {
1022
1527
  return this.messages.fetchMany(options);
@@ -1024,16 +1529,72 @@ var BaseChannel = class extends Base {
1024
1529
  /**
1025
1530
  * Edits this channel.
1026
1531
  * @param options The fields to update
1532
+ * @throws {Error} If the API request fails
1533
+ * @returns BaseChannel
1534
+ * @example
1535
+ * // Edit the channel's name
1536
+ * await channel.edit({name: "New Cool Name"});
1027
1537
  */
1028
1538
  async edit(options) {
1029
1539
  return await this.client.channels.edit(this.id, options);
1030
1540
  }
1031
1541
  /**
1032
1542
  * Deletes this channel.
1543
+ * @throws {Error} If the API request fails
1544
+ * @example
1545
+ * // Delete the channel
1546
+ * await channel.delete();
1033
1547
  */
1034
1548
  async delete() {
1035
1549
  await this.client.channels.delete(this.id);
1036
1550
  }
1551
+ /**
1552
+ * Bulk delete messages from this channel
1553
+ * @param messages MessageResolvable to delete
1554
+ * @throws {Error} If the API request fails
1555
+ * @example
1556
+ * // Delete messages by their ID's
1557
+ * await channel.bulkDelete(["MESSAGE_ID_1", "MESSAGE_ID_2", "MESSAGE_ID_3"]);
1558
+ * // Delete messages by their Message objects
1559
+ * await channel.bulkDelete([message1, message2, message3]);
1560
+ */
1561
+ async bulkDelete(messages) {
1562
+ await this.client.channels.bulkDelete(this.id, messages);
1563
+ }
1564
+ /**
1565
+ * Creates a MessageCollector to collect messages in this channel.
1566
+ * @param options The options for the collector.
1567
+ * @returns The instantiated MessageCollector
1568
+ * @example
1569
+ * const collector = channel.createMessageCollector({ filter: m => m.authorId === '123', time: 15000 });
1570
+ * collector.on('collect', m => console.log(`Collected ${m.content}`));
1571
+ * collector.on('end', collected => console.log(`Collected ${collected.size} items`));
1572
+ */
1573
+ createMessageCollector(options) {
1574
+ return new MessageCollector(this, options);
1575
+ }
1576
+ /**
1577
+ * Awaits messages in this channel that meet certain criteria.
1578
+ * @param options The options for the collector.
1579
+ * @returns A promise that resolves to a collection of messages.
1580
+ * @example
1581
+ * // Await !vote messages
1582
+ * const filter = m => m.content.startsWith('!vote');
1583
+ * channel.awaitMessages({ filter, max: 4, time: 60000 })
1584
+ * .then(collected => console.log(collected.size))
1585
+ * .catch(console.error);
1586
+ */
1587
+ awaitMessages(options = {}) {
1588
+ return new Promise((resolve, reject) => {
1589
+ const collector = this.createMessageCollector(options);
1590
+ collector.once("end", (collected, reason) => {
1591
+ if (options.max && reason !== "limit" && reason !== "time") {
1592
+ return reject(new Error(`Collector ended with reason: ${reason}`));
1593
+ }
1594
+ resolve(collected);
1595
+ });
1596
+ });
1597
+ }
1037
1598
  isText() {
1038
1599
  return this.type === "TextChannel" /* TEXT */;
1039
1600
  }
@@ -1077,6 +1638,15 @@ var TextChannel = class extends BaseChannel {
1077
1638
  case "Description":
1078
1639
  this.description = null;
1079
1640
  break;
1641
+ case "Icon":
1642
+ this.icon = null;
1643
+ break;
1644
+ case "DefaultPermissions":
1645
+ this.defaultPermissions = data.default_permissions;
1646
+ break;
1647
+ case "Voice":
1648
+ this.voice = data.voice;
1649
+ break;
1080
1650
  }
1081
1651
  }
1082
1652
  }
@@ -1108,6 +1678,136 @@ var TextChannel = class extends BaseChannel {
1108
1678
  async setDefaultPermissions(permissions) {
1109
1679
  return await this.client.channels.setDefaultPermissions(this.id, permissions);
1110
1680
  }
1681
+ /**
1682
+ * Edits the category of this channel. Only applicable to server channels.
1683
+ * @param category The ID of the category to move this channel into, or "default" to remove from any category.
1684
+ * @returns The updated TextChannel with the new category.
1685
+ * @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.
1686
+ * @example
1687
+ * // Move this channel into a category
1688
+ * await channel.setCategory("CATEGORY_ID");
1689
+ * // Remove this channel from its category
1690
+ * await channel.setCategory("default");
1691
+ */
1692
+ async setCategory(category) {
1693
+ const serverId = this.serverId;
1694
+ const server = await this.client.servers.fetch(serverId);
1695
+ const categories = server.categories.map((c) => ({
1696
+ id: c.id,
1697
+ title: c.title,
1698
+ channels: [...c.channels]
1699
+ }));
1700
+ for (const cat of categories) {
1701
+ cat.channels = cat.channels.filter((id) => id !== this.id);
1702
+ }
1703
+ if (category !== "default") {
1704
+ const targetCategory = categories.find((c) => c.id === category);
1705
+ if (!targetCategory) {
1706
+ throw new Error(`Category ${category} not found in server.`);
1707
+ }
1708
+ targetCategory.channels.push(this.id);
1709
+ }
1710
+ await this.client.servers.edit(serverId, { categories });
1711
+ return this;
1712
+ }
1713
+ /**
1714
+ * Sets the position of this channel within its current category.
1715
+ * @param position The new index position for the channel within its category.
1716
+ * @returns The updated TextChannel.
1717
+ * @throws {Error} If the channel is not in a category, or if the API request fails.
1718
+ * @example
1719
+ * // Move channel to the top of its category
1720
+ * await channel.setPosition(0);
1721
+ */
1722
+ async setPosition(position) {
1723
+ const serverId = this.serverId;
1724
+ const server = await this.client.servers.fetch(serverId);
1725
+ const categories = server.categories.map((c) => ({
1726
+ id: c.id,
1727
+ title: c.title,
1728
+ channels: [...c.channels]
1729
+ }));
1730
+ const currentCategory = categories.find((c) => c.channels.includes(this.id));
1731
+ if (!currentCategory) {
1732
+ throw new Error("This channel is not currently inside any category.");
1733
+ }
1734
+ currentCategory.channels = currentCategory.channels.filter((id) => id !== this.id);
1735
+ const safePosition = Math.max(0, Math.min(position, currentCategory.channels.length));
1736
+ currentCategory.channels.splice(safePosition, 0, this.id);
1737
+ await this.client.servers.edit(serverId, { categories });
1738
+ return this;
1739
+ }
1740
+ /**
1741
+ * Edit the description of this channel
1742
+ * @param description
1743
+ * @throws {Error} If the API request fails
1744
+ * @returns The updated TextChannel
1745
+ * @example
1746
+ * // Set the channel description
1747
+ * await channel.setDescription("This is a channel about cats!");
1748
+ * // Remove the channel description
1749
+ * await channel.setDescription(null);
1750
+ */
1751
+ async setDescription(description) {
1752
+ await this.edit({ description });
1753
+ return this;
1754
+ }
1755
+ /**
1756
+ * Edit the name of this channel
1757
+ * @param name
1758
+ * @throws {Error} If the API request fails
1759
+ * @returns The updated TextChannel
1760
+ * @example
1761
+ * await channel.setName("New Name");
1762
+ */
1763
+ async setName(name) {
1764
+ await this.edit({ name });
1765
+ return this;
1766
+ }
1767
+ /**
1768
+ * Set whether this channel is NSFW
1769
+ * @param nsfw
1770
+ * @throws {Error} If the API request fails
1771
+ * @returns The updated TextChannel
1772
+ * @example
1773
+ * // Mark the channel as NSFW
1774
+ * await channel.setNSFW(true);
1775
+ * // Mark the channel as SFW
1776
+ * await channel.setNSFW(false);
1777
+ */
1778
+ async setNSFW(nsfw) {
1779
+ await this.edit({ nsfw });
1780
+ return this;
1781
+ }
1782
+ /**
1783
+ * Set the channel slowmode in seconds
1784
+ * @param slowmode
1785
+ * @throws {Error} If the API request fails
1786
+ * @returns The updated TextChannel
1787
+ * @example
1788
+ * // Set the slowmode to 5 seconds
1789
+ * await channel.setSlowmode(5);
1790
+ * // Remove slowmode
1791
+ * await channel.setSlowmode(0);
1792
+ */
1793
+ async setSlowmode(slowmode) {
1794
+ await this.edit({ slowmode });
1795
+ return this;
1796
+ }
1797
+ /**
1798
+ * Set the channel Icon
1799
+ * @param id Autumn ID to use
1800
+ * @throws {Error} If the API request fails
1801
+ * @returns The updated TextChannel
1802
+ * @example
1803
+ * await channel.setIcon("123");
1804
+ * // Remove the channel icon
1805
+ * await channel.setIcon(null);
1806
+ */
1807
+ async setIcon(id) {
1808
+ await this.edit({ icon: id });
1809
+ return this;
1810
+ }
1111
1811
  };
1112
1812
 
1113
1813
  // src/structures/UnknownChannel.ts
@@ -1133,7 +1833,7 @@ var DMChannel = class extends BaseChannel {
1133
1833
  };
1134
1834
 
1135
1835
  // src/structures/GroupChannel.ts
1136
- import * as util3 from "util";
1836
+ import * as util4 from "util";
1137
1837
  var GroupChannel = class extends BaseChannel {
1138
1838
  name;
1139
1839
  ownerId;
@@ -1193,9 +1893,9 @@ var GroupChannel = class extends BaseChannel {
1193
1893
  async setDefaultPermissions(permissions) {
1194
1894
  return await this.client.channels.setDefaultPermissions(this.id, permissions);
1195
1895
  }
1196
- [util3.inspect.custom](_depth, options, inspect10) {
1896
+ [util4.inspect.custom](_depth, options, inspect12) {
1197
1897
  const { client, ...props } = this;
1198
- return `${this.constructor.name} ${inspect10(
1898
+ return `${this.constructor.name} ${inspect12(
1199
1899
  {
1200
1900
  ...props,
1201
1901
  owner: this.owner,
@@ -1346,7 +2046,7 @@ var ChannelManager = class extends BaseManager {
1346
2046
  /**
1347
2047
  * Fetches a Channel from the API or resolves it from the local cache.
1348
2048
  * @param channel The ID, mention, or Channel object to fetch.
1349
- * @param force Whether to skip the cache check and force a direct API request. Defaults to true.
2049
+ * @param force Whether to skip the cache check and force a direct API request. Defaults to false.
1350
2050
  * @returns A promise that resolves to the fetched BaseChannel object.
1351
2051
  * @throws {TypeError} If an invalid ChannelResolvable is provided.
1352
2052
  * @throws {Error} If the API request fails.
@@ -1354,7 +2054,7 @@ var ChannelManager = class extends BaseManager {
1354
2054
  * // Fetch a channel, bypassing cache
1355
2055
  * const channel = await client.channels.fetch("01H...");
1356
2056
  */
1357
- async fetch(channel, force = true) {
2057
+ async fetch(channel, force = false) {
1358
2058
  if (!force) {
1359
2059
  const cached = this.resolve(channel);
1360
2060
  if (cached) return cached;
@@ -1468,10 +2168,51 @@ var ChannelManager = class extends BaseManager {
1468
2168
  await this.client.rest.delete(`/channels/${id}`);
1469
2169
  this.cache.delete(id);
1470
2170
  }
2171
+ /**
2172
+ * Pin a message
2173
+ * @param id Channel ID
2174
+ * @param messageId Message ID
2175
+ * @throws {Error} If the API request fails.
2176
+ * @example
2177
+ * await client.channels.pin("CHANNEL_ID", "MESSAGE_ID");
2178
+ */
2179
+ async pin(id, messageId) {
2180
+ await this.client.rest.post(`/channels/${id}/pins/${messageId}`);
2181
+ }
2182
+ /**
2183
+ * Unpin a message
2184
+ * @param id Channel ID
2185
+ * @param messageId Message ID
2186
+ * @throws {Error} If the API request fails
2187
+ * @example
2188
+ * await client.channels.unpin("CHANNEL_ID", "MESSAGE_ID");
2189
+ */
2190
+ async unpin(id, messageId) {
2191
+ await this.client.rest.delete(`/channels/${id}/pins/${messageId}`);
2192
+ }
2193
+ /**
2194
+ * Bulk delete up to 100 messages
2195
+ * @param id Channel ID
2196
+ * @param messages An array of MessageResolvable
2197
+ * @throws {Error} If the API request fails
2198
+ * @example
2199
+ * await client.channels.bulkDelete("CHANNEL_ID", ["MESSAGE_ID_1", "MESSAGE_ID_2", "MESSAGE_ID_3"]);
2200
+ */
2201
+ async bulkDelete(id, messages) {
2202
+ if (!Array.isArray(messages) || messages.length === 0 || messages.length > 100) {
2203
+ throw new TypeError("Messages must be an array of 1-100 MessageResolvable items.");
2204
+ }
2205
+ const messageIds = messages.map((msg) => {
2206
+ if (typeof msg === "string") return msg.replace(/[<#>]/g, "");
2207
+ if ("id" in msg) return msg.id;
2208
+ throw new TypeError("Invalid MessageResolvable provided. Expected a Message object or a string ID/Mention.");
2209
+ });
2210
+ await this.client.rest.delete(`/channels/${id}/messages/bulk`, { messages: messageIds });
2211
+ }
1471
2212
  };
1472
2213
 
1473
2214
  // src/structures/Member.ts
1474
- import * as util4 from "util";
2215
+ import * as util5 from "util";
1475
2216
 
1476
2217
  // src/managers/MemberRoleManager.ts
1477
2218
  var MemberRoleManager = class {
@@ -1650,9 +2391,24 @@ var Member = class extends Base {
1650
2391
  * await member.setTimeout(600000);
1651
2392
  */
1652
2393
  async setTimeout(duration) {
1653
- let server = this.server;
1654
- if (!server) server = await this.client.servers.fetch(this.serverId);
1655
- await server.members.setTimeout(this.id, duration);
2394
+ await this.edit({ timeout: new Date(Date.now() + duration).toISOString() });
2395
+ }
2396
+ /**
2397
+ * Send a message to this member.
2398
+ * @param options The content or options for the message to send.
2399
+ * @returns A promise that resolves to the sent Message object.
2400
+ * @throws {Error} If the API request fails.
2401
+ * @example
2402
+ * // Send a message to this member
2403
+ * const message = await member.send("Hello!");
2404
+ * console.log(`Sent message ID: ${message.id}`);
2405
+ */
2406
+ async send(options) {
2407
+ let dmChannel = await this.client.users.createDM(this.id);
2408
+ return dmChannel.messages.send(options);
2409
+ }
2410
+ async setNickname(nickname) {
2411
+ return this.edit({ nickname });
1656
2412
  }
1657
2413
  /** Checks if the member has a specific permission */
1658
2414
  hasPermission(permission) {
@@ -1668,6 +2424,16 @@ var Member = class extends Base {
1668
2424
  if (!server) server = await this.client.servers.fetch(this.serverId);
1669
2425
  return await server.members.edit(this.id, options);
1670
2426
  }
2427
+ /**
2428
+ * When concatenated with a string, this automatically returns the user's mention instead of the GuildMember object.
2429
+ * @returns {string}
2430
+ * @example
2431
+ * // Logs: Hello from <@01JE2MM759J5D7CHJF084R7MJ2>!
2432
+ * console.log(`Hello from ${member}!`);
2433
+ */
2434
+ toString() {
2435
+ return `<@${this.id}>`;
2436
+ }
1671
2437
  /**
1672
2438
  * Kick this member from the server.
1673
2439
  */
@@ -1677,9 +2443,9 @@ var Member = class extends Base {
1677
2443
  await server.members.kick(this.id);
1678
2444
  }
1679
2445
  /** @internal */
1680
- [util4.inspect.custom](depth, options, inspect10) {
2446
+ [util5.inspect.custom](depth, options, inspect12) {
1681
2447
  const { client, serverId, ...props } = this;
1682
- return `${this.constructor.name} ${inspect10(
2448
+ return `${this.constructor.name} ${inspect12(
1683
2449
  {
1684
2450
  ...props,
1685
2451
  user: this.user,
@@ -1691,7 +2457,7 @@ var Member = class extends Base {
1691
2457
  };
1692
2458
 
1693
2459
  // src/managers/MemberManager.ts
1694
- import * as util5 from "util";
2460
+ import * as util6 from "util";
1695
2461
  var MemberManager = class extends BaseManager {
1696
2462
  constructor(client, server, limit = Infinity) {
1697
2463
  super(client, limit);
@@ -1865,25 +2631,13 @@ var MemberManager = class extends BaseManager {
1865
2631
  const id = this.resolveId(member);
1866
2632
  await this.client.rest.delete(`/servers/${this.server.id}/bans/${id}`);
1867
2633
  }
1868
- /**
1869
- * Timeouts a member in the server for a specified duration.
1870
- * @param member The MemberResolvable to timeout
1871
- * @param duration The duration of the timeout in milliseconds
1872
- * @example
1873
- * // Timeout a member for 10 minutes
1874
- * await server.members.setTimeout("1234567890", 10 * 60 * 1000);
1875
- */
1876
- async setTimeout(member, duration) {
1877
- const id = this.resolveId(member);
1878
- await this.edit(id, { timeout: new Date(Date.now() + duration).toISOString() });
1879
- }
1880
- [util5.inspect.custom]() {
2634
+ [util6.inspect.custom]() {
1881
2635
  return this.cache;
1882
2636
  }
1883
2637
  };
1884
2638
 
1885
2639
  // src/managers/ServerChannelManager.ts
1886
- import * as util6 from "util";
2640
+ import * as util7 from "util";
1887
2641
  var ServerChannelManager = class {
1888
2642
  client;
1889
2643
  server;
@@ -1913,13 +2667,13 @@ var ServerChannelManager = class {
1913
2667
  const data = await this.client.rest.post(`/servers/${this.server.id}/channels`, payload);
1914
2668
  return this.client.channels._add(data);
1915
2669
  }
1916
- [util6.inspect.custom]() {
2670
+ [util7.inspect.custom]() {
1917
2671
  return this.cache;
1918
2672
  }
1919
2673
  };
1920
2674
 
1921
2675
  // src/structures/Role.ts
1922
- import * as util7 from "util";
2676
+ import * as util8 from "util";
1923
2677
  var Role = class extends Base {
1924
2678
  serverId;
1925
2679
  name;
@@ -2062,14 +2816,14 @@ var Role = class extends Base {
2062
2816
  * Hides the cyclic client reference and raw serverId for a cleaner output.
2063
2817
  * @internal
2064
2818
  */
2065
- [util7.inspect.custom]() {
2819
+ [util8.inspect.custom]() {
2066
2820
  const { client, serverId, ...props } = this;
2067
- return `${this.constructor.name} ${util7.inspect(props)}`;
2821
+ return `${this.constructor.name} ${util8.inspect(props)}`;
2068
2822
  }
2069
2823
  };
2070
2824
 
2071
2825
  // src/managers/RoleManager.ts
2072
- import * as util8 from "util";
2826
+ import * as util9 from "util";
2073
2827
  var RoleManager = class extends BaseManager {
2074
2828
  /**
2075
2829
  * Manages API methods and caching for server roles.
@@ -2108,7 +2862,7 @@ var RoleManager = class extends BaseManager {
2108
2862
  this.cache.set(role.id, role);
2109
2863
  return role;
2110
2864
  }
2111
- [util8.inspect.custom]() {
2865
+ [util9.inspect.custom]() {
2112
2866
  return this.cache;
2113
2867
  }
2114
2868
  /**
@@ -2409,6 +3163,54 @@ var ServerBanManager = class extends BaseManager {
2409
3163
  }
2410
3164
  };
2411
3165
 
3166
+ // src/structures/Emoji.ts
3167
+ var Emoji = class extends Base {
3168
+ creatorId;
3169
+ name;
3170
+ parent;
3171
+ animated = false;
3172
+ nsfw = false;
3173
+ constructor(client, data) {
3174
+ super(client, data);
3175
+ this._patch(data);
3176
+ }
3177
+ _patch(data) {
3178
+ if (data.creator_id !== void 0) this.creatorId = data.creator_id;
3179
+ if (data.name !== void 0) this.name = data.name;
3180
+ if (data.parent !== void 0) this.parent = data.parent;
3181
+ if (data.animated !== void 0) this.animated = data.animated;
3182
+ if (data.nsfw !== void 0) this.nsfw = data.nsfw;
3183
+ }
3184
+ };
3185
+
3186
+ // src/managers/EmojiManager.ts
3187
+ import * as util10 from "util";
3188
+ var EmojiManager = class extends BaseManager {
3189
+ constructor(client, server, limit = Infinity) {
3190
+ super(client, limit);
3191
+ this.server = server;
3192
+ }
3193
+ /**
3194
+ * Tell BaseManager how to find the ID for Emojis
3195
+ */
3196
+ extractId(data) {
3197
+ return data._id ?? data.id;
3198
+ }
3199
+ /**
3200
+ * Tell BaseManager how to build an Emoji
3201
+ */
3202
+ construct(data) {
3203
+ return new Emoji(this.client, data);
3204
+ }
3205
+ async fetch(id) {
3206
+ const data = await this.client.rest.get(`/custom/emoji/${id}`);
3207
+ return this._add(data);
3208
+ }
3209
+ [util10.inspect.custom]() {
3210
+ return this.cache;
3211
+ }
3212
+ };
3213
+
2412
3214
  // src/structures/Server.ts
2413
3215
  var Server = class extends Base {
2414
3216
  channelIds = [];
@@ -2428,6 +3230,7 @@ var Server = class extends Base {
2428
3230
  roles;
2429
3231
  bans;
2430
3232
  invites;
3233
+ emojis;
2431
3234
  constructor(client, data) {
2432
3235
  super(client, data);
2433
3236
  this.channels = new ServerChannelManager(client, this);
@@ -2435,6 +3238,7 @@ var Server = class extends Base {
2435
3238
  this.roles = new RoleManager(client, this);
2436
3239
  this.bans = new ServerBanManager(this.client, this);
2437
3240
  this.invites = new ServerInviteManager(this.client, this);
3241
+ this.emojis = new EmojiManager(this.client, this);
2438
3242
  this._patch(data);
2439
3243
  }
2440
3244
  /**
@@ -2468,6 +3272,13 @@ var Server = class extends Base {
2468
3272
  this.roles._add({ id, ...roleData });
2469
3273
  }
2470
3274
  }
3275
+ if (data.emojis !== void 0) {
3276
+ if (Array.isArray(data.emojis)) {
3277
+ for (const emoji of data.emojis) {
3278
+ this.emojis._add(emoji);
3279
+ }
3280
+ }
3281
+ }
2471
3282
  if (clear && Array.isArray(clear)) {
2472
3283
  for (const field of clear) {
2473
3284
  switch (field) {
@@ -2506,7 +3317,7 @@ var Server = class extends Base {
2506
3317
  };
2507
3318
 
2508
3319
  // src/managers/ServerManager.ts
2509
- import * as util9 from "util";
3320
+ import * as util11 from "util";
2510
3321
  var ServerManager = class extends BaseManager {
2511
3322
  constructor(client, limit = Infinity) {
2512
3323
  super(client, limit);
@@ -2579,7 +3390,7 @@ var ServerManager = class extends BaseManager {
2579
3390
  const data = await this.client.rest.patch(`/servers/${serverId}`, payload);
2580
3391
  return this._add(data);
2581
3392
  }
2582
- [util9.inspect.custom]() {
3393
+ [util11.inspect.custom]() {
2583
3394
  return this.cache;
2584
3395
  }
2585
3396
  };
@@ -2808,7 +3619,7 @@ var SweeperManager = class {
2808
3619
  };
2809
3620
 
2810
3621
  // src/client/Client.ts
2811
- var Client = class extends EventEmitter {
3622
+ var Client = class extends EventEmitter2 {
2812
3623
  constructor(options = {}) {
2813
3624
  super({ captureRejections: true });
2814
3625
  this.options = options;
@@ -2817,6 +3628,7 @@ var Client = class extends EventEmitter {
2817
3628
  this.channels = new ChannelManager(this, options.cacheLimits?.channels);
2818
3629
  this.servers = new ServerManager(this, options.cacheLimits?.servers);
2819
3630
  this.users = new UserManager(this, options.cacheLimits?.users);
3631
+ this.emojis = new EmojiManager(this, void 0, options.cacheLimits?.emojis);
2820
3632
  this.sweepers = new SweeperManager(this, options.sweepers ?? {});
2821
3633
  }
2822
3634
  rest;
@@ -2825,6 +3637,7 @@ var Client = class extends EventEmitter {
2825
3637
  servers;
2826
3638
  users;
2827
3639
  sweepers;
3640
+ emojis;
2828
3641
  user = null;
2829
3642
  /**
2830
3643
  * Connects the bot to the Stoat Gateway
@@ -2895,16 +3708,22 @@ export {
2895
3708
  Client,
2896
3709
  ClientUser,
2897
3710
  Collection,
3711
+ Collector,
2898
3712
  DMChannel,
2899
3713
  EmbedBuilder,
3714
+ Emoji,
3715
+ EmojiManager,
2900
3716
  GatewayManager,
2901
3717
  Member,
2902
3718
  MemberManager,
2903
3719
  Message,
3720
+ MessageCollector,
2904
3721
  MessageManager,
3722
+ MessageReaction,
2905
3723
  PermissionFlags,
2906
3724
  Permissions,
2907
3725
  RESTManager,
3726
+ ReactionCollector,
2908
3727
  Role,
2909
3728
  RoleManager,
2910
3729
  Server,