@stoatx/client 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,2800 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Attachment: () => Attachment,
34
+ Base: () => Base,
35
+ BaseChannel: () => BaseChannel,
36
+ ChannelManager: () => ChannelManager,
37
+ ChannelType: () => ChannelType,
38
+ Client: () => Client,
39
+ ClientUser: () => ClientUser,
40
+ Collection: () => Collection,
41
+ DMChannel: () => DMChannel,
42
+ EmbedBuilder: () => EmbedBuilder,
43
+ GatewayManager: () => GatewayManager,
44
+ Member: () => Member,
45
+ MemberManager: () => MemberManager,
46
+ Message: () => Message,
47
+ MessageManager: () => MessageManager,
48
+ PermissionFlags: () => PermissionFlags,
49
+ Permissions: () => Permissions,
50
+ RESTManager: () => RESTManager,
51
+ Role: () => Role,
52
+ RoleManager: () => RoleManager,
53
+ Server: () => Server,
54
+ ServerChannelManager: () => ServerChannelManager,
55
+ ServerManager: () => ServerManager,
56
+ SweeperManager: () => SweeperManager,
57
+ TextChannel: () => TextChannel,
58
+ UnknownChannel: () => UnknownChannel,
59
+ User: () => User,
60
+ UserManager: () => UserManager,
61
+ UserPresence: () => UserPresence,
62
+ UserRelationship: () => UserRelationship
63
+ });
64
+ module.exports = __toCommonJS(index_exports);
65
+
66
+ // src/client/Client.ts
67
+ var import_events = require("events");
68
+
69
+ // src/gateway/GatewayManager.ts
70
+ var import_ws = __toESM(require("ws"), 1);
71
+
72
+ // src/structures/Base.ts
73
+ var Base = class _Base {
74
+ id;
75
+ cachedAt = Date.now();
76
+ client;
77
+ constructor(client, data) {
78
+ this.id = data._id;
79
+ this.client = client;
80
+ Object.defineProperty(this, "client", {
81
+ value: client,
82
+ enumerable: false,
83
+ writable: false
84
+ });
85
+ }
86
+ /**
87
+ * Compares this object with another to see if they represent the same entity.
88
+ */
89
+ equals(other) {
90
+ if (typeof other === "string") return this.id === other;
91
+ return other instanceof _Base && this.id === other.id;
92
+ }
93
+ /**
94
+ * Returns the UUID string when the object is cast to a string.
95
+ */
96
+ toString() {
97
+ return this.id;
98
+ }
99
+ /**
100
+ * Helper to quickly clone a structure
101
+ */
102
+ _clone() {
103
+ return Object.assign(Object.create(this), this);
104
+ }
105
+ };
106
+
107
+ // src/structures/Message.ts
108
+ var util = __toESM(require("util"), 1);
109
+
110
+ // src/structures/Attachment.ts
111
+ var Attachment = class extends Base {
112
+ id;
113
+ tag;
114
+ filename;
115
+ metadata;
116
+ contentType;
117
+ size;
118
+ deleted;
119
+ reported;
120
+ messageId;
121
+ userId;
122
+ serverId;
123
+ objectId;
124
+ constructor(client, data) {
125
+ super(client, { ...data, id: data._id });
126
+ this.id = data._id;
127
+ this.tag = data.tag;
128
+ this.filename = data.filename;
129
+ this.metadata = data.metadata ?? { type: "File" };
130
+ this.contentType = data.content_type;
131
+ this.size = data.size;
132
+ this.deleted = data.deleted ?? false;
133
+ this.reported = data.reported ?? false;
134
+ this.messageId = data.message_id;
135
+ this.userId = data.user_id;
136
+ this.serverId = data.server_id;
137
+ this.objectId = data.object_id;
138
+ }
139
+ /**
140
+ * Automatically constructs the direct CDN URL for this file
141
+ */
142
+ get url() {
143
+ return `https://cdn.stoatusercontent.com/${this.tag}/${this.id}/${this.filename}`;
144
+ }
145
+ /**
146
+ * Helper boolean to quickly check if it's an image
147
+ */
148
+ get isImage() {
149
+ return this.metadata.type === "Image";
150
+ }
151
+ };
152
+
153
+ // src/structures/Message.ts
154
+ var import_ulid = require("ulid");
155
+ var Message = class extends Base {
156
+ content = null;
157
+ authorId;
158
+ channelId;
159
+ embeds = [];
160
+ attachments = [];
161
+ editedAt = null;
162
+ createdAt = null;
163
+ flags = 0;
164
+ interactions = null;
165
+ masquerade = null;
166
+ mentions = [];
167
+ pinned = false;
168
+ reactions = [];
169
+ replies = [];
170
+ role_mentions = [];
171
+ constructor(client, data) {
172
+ super(client, data);
173
+ this.authorId = data.author;
174
+ this.channelId = data.channel;
175
+ const timestamp = (0, import_ulid.decodeTime)(this.id);
176
+ if (timestamp) {
177
+ console.log(timestamp);
178
+ this.createdAt = new Date(timestamp);
179
+ }
180
+ if (data.attachments) {
181
+ this.attachments = data.attachments.map((fileData) => new Attachment(this.client, fileData));
182
+ }
183
+ if (data.masquerade !== void 0) this.masquerade = data.masquerade;
184
+ if (data.mentions !== void 0) this.mentions = data.mentions;
185
+ if (data.replies !== void 0) this.replies = data.replies;
186
+ if (data.role_mentions !== void 0) this.role_mentions = data.role_mentions;
187
+ this._patch(data);
188
+ }
189
+ async reply(contentOrOptions) {
190
+ let channel = this.channel;
191
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
192
+ const options = typeof contentOrOptions === "string" ? { content: contentOrOptions } : { ...contentOrOptions };
193
+ const repliesArray = options.replies ? [...options.replies] : [];
194
+ const alreadyReplying = repliesArray.some((reply) => reply.id === this.id);
195
+ if (!alreadyReplying) {
196
+ repliesArray.push({
197
+ id: this.id,
198
+ mention: true
199
+ });
200
+ }
201
+ options.replies = repliesArray;
202
+ return channel.messages.send(options);
203
+ }
204
+ /**
205
+ * Edits this message.
206
+ * @param contentOrOptions The new content or options for the message.
207
+ */
208
+ async edit(contentOrOptions) {
209
+ let channel = this.channel;
210
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
211
+ return await channel.messages.edit(this.id, contentOrOptions);
212
+ }
213
+ /**
214
+ * Deletes this message.
215
+ */
216
+ async delete() {
217
+ let channel = this.channel;
218
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
219
+ await channel.messages.delete(this.id);
220
+ }
221
+ /**
222
+ * Pins this message.
223
+ */
224
+ async pin() {
225
+ let channel = this.channel;
226
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
227
+ await channel.messages.pin(this.id);
228
+ }
229
+ /**
230
+ * Unpins this message.
231
+ */
232
+ async unpin() {
233
+ let channel = this.channel;
234
+ if (!channel) channel = await this.client.channels.fetch(this.channelId);
235
+ await channel.messages.unpin(this.id);
236
+ }
237
+ /** Gets the Channel object from cache */
238
+ get channel() {
239
+ return this.client.channels.cache.get(this.channelId);
240
+ }
241
+ /** Gets the Global User object from cache */
242
+ get author() {
243
+ return this.client.users.cache.get(this.authorId);
244
+ }
245
+ /** Gets the Server Member object (if sent in a server) */
246
+ get member() {
247
+ const channel = this.channel;
248
+ if (channel && "serverId" in channel) {
249
+ const server = this.client.servers.cache.get(channel.serverId);
250
+ return server?.members.cache.get(this.authorId);
251
+ }
252
+ return void 0;
253
+ }
254
+ /** Gets the Server ID if this message was sent in a server channel */
255
+ get serverId() {
256
+ const channel = this.channel;
257
+ if (channel && "serverId" in channel) {
258
+ return channel.serverId;
259
+ }
260
+ return void 0;
261
+ }
262
+ /** Gets the Server object from cache */
263
+ get server() {
264
+ const serverId = this.serverId;
265
+ if (!serverId) return void 0;
266
+ return this.client.servers.cache.get(serverId);
267
+ }
268
+ _patch(data) {
269
+ if (data.content !== void 0) this.content = data.content;
270
+ if (data.edited !== void 0) this.editedAt = new Date(data.edited);
271
+ if (data.pinned !== void 0) this.pinned = data.pinned;
272
+ if (data.embeds !== void 0) this.embeds = data.embeds;
273
+ if (data.flags !== void 0) this.flags = data.flags;
274
+ if (data.reactions !== void 0) this.reactions = data.reactions;
275
+ if (data.interactions !== void 0) {
276
+ if (data.interactions) {
277
+ this.interactions = {
278
+ reactions: data.interactions.reactions ?? [],
279
+ restrictReactions: data.interactions.restrict_reactions ?? false
280
+ };
281
+ } else {
282
+ this.interactions = null;
283
+ }
284
+ }
285
+ }
286
+ // This tells Node.js exactly how to print this object in console.log()
287
+ [util.inspect.custom](depth, options, inspect10) {
288
+ const { client, authorId, channelId, ...props } = this;
289
+ const data = {
290
+ ...props,
291
+ author: this.author,
292
+ channel: this.channel,
293
+ server: this.server,
294
+ member: this.member
295
+ };
296
+ return `${this.constructor.name} ${inspect10(data, { ...options, depth: depth ?? options.depth })}`;
297
+ }
298
+ };
299
+
300
+ // src/structures/User.ts
301
+ var UserRelationship = /* @__PURE__ */ ((UserRelationship2) => {
302
+ UserRelationship2["None"] = "None";
303
+ UserRelationship2["User"] = "User";
304
+ UserRelationship2["Friend"] = "Friend";
305
+ UserRelationship2["Outgoing"] = "Outgoing";
306
+ UserRelationship2["Incoming"] = "Incoming";
307
+ UserRelationship2["Blocked"] = "Blocked";
308
+ UserRelationship2["BlockedOther"] = "BlockedOther";
309
+ return UserRelationship2;
310
+ })(UserRelationship || {});
311
+ var UserPresence = /* @__PURE__ */ ((UserPresence2) => {
312
+ UserPresence2["Online"] = "Online";
313
+ UserPresence2["Idle"] = "Idle";
314
+ UserPresence2["Focus"] = "Focus";
315
+ UserPresence2["Busy"] = "Busy";
316
+ UserPresence2["Invisible"] = "Invisible";
317
+ return UserPresence2;
318
+ })(UserPresence || {});
319
+ var User = class extends Base {
320
+ discriminator;
321
+ online;
322
+ relationship;
323
+ username;
324
+ avatar;
325
+ badges;
326
+ bot;
327
+ displayName;
328
+ flags;
329
+ privileged;
330
+ status;
331
+ constructor(client, data) {
332
+ super(client, data);
333
+ this.bot = false;
334
+ this.privileged = false;
335
+ this.flags = 0;
336
+ this._patch(data);
337
+ }
338
+ _patch(data, clear) {
339
+ if (data.username !== void 0) this.username = data.username;
340
+ if (data.discriminator !== void 0) this.discriminator = data.discriminator;
341
+ if (data.online !== void 0) this.online = data.online;
342
+ if (data.relationship !== void 0) this.relationship = data.relationship;
343
+ if (data.display_name !== void 0) this.displayName = data.display_name;
344
+ if (data.badges !== void 0) this.badges = data.badges;
345
+ if (data.flags !== void 0) this.flags = data.flags;
346
+ if (data.privileged !== void 0) this.privileged = data.privileged ?? false;
347
+ if (data.status !== void 0) this.status = data.status;
348
+ if (data.bot !== void 0) {
349
+ this.bot = data.bot ? { owner: data.bot.owner } : false;
350
+ }
351
+ if (data.avatar !== void 0) {
352
+ this.avatar = new Attachment(this.client, data.avatar);
353
+ }
354
+ if (clear && Array.isArray(clear)) {
355
+ for (const field of clear) {
356
+ if (field === "Avatar") this.avatar = null;
357
+ if (field === "StatusText" && this.status) this.status.text = null;
358
+ if (field === "DisplayName") this.displayName = null;
359
+ }
360
+ }
361
+ }
362
+ /**
363
+ * Convenience getter to return the user's tag (username#discriminator)
364
+ */
365
+ get tag() {
366
+ return `${this.username}#${this.discriminator}`;
367
+ }
368
+ /**
369
+ * Fetch a User to update their information
370
+ * @param force Skip the cache check and force an API request
371
+ * @returns The fetched User object
372
+ * @throws Error if the user cannot be found or fetched
373
+ * @example
374
+ * // Fetch a user
375
+ * await user.fetch();
376
+ */
377
+ async fetch(force = false) {
378
+ return await this.client.users.fetch(this.id, force);
379
+ }
380
+ };
381
+
382
+ // src/structures/ClientUser.ts
383
+ var ClientUser = class extends User {
384
+ constructor(client, data) {
385
+ super(client, data);
386
+ }
387
+ };
388
+
389
+ // src/gateway/GatewayManager.ts
390
+ var GatewayManager = class {
391
+ constructor(client) {
392
+ this.client = client;
393
+ }
394
+ ws = null;
395
+ pingInterval = null;
396
+ token = null;
397
+ reconnectAttempts = 0;
398
+ maxReconnectWait = 6e4;
399
+ // Cap at 60s
400
+ isIntentionalClose = false;
401
+ async connect(token) {
402
+ this.token = token;
403
+ this.isIntentionalClose = false;
404
+ this.client.emit("debug", "Connecting to Stoat Gateway...");
405
+ if (this.ws) {
406
+ this.ws.removeAllListeners();
407
+ this.ws = null;
408
+ }
409
+ const baseUrl = "wss://stoat.chat/events";
410
+ const url = `${baseUrl}?version=1&format=json&token=${this.token}`;
411
+ this.ws = new import_ws.default(url);
412
+ this.ws.on("open", () => {
413
+ this.client.emit("debug", "WebSocket Opened. Starting ping loop...");
414
+ this.reconnectAttempts = 0;
415
+ this.startPingLoop();
416
+ });
417
+ this.ws.on("message", (data) => this.handleMessage(data));
418
+ this.ws.on("close", (code, reason) => {
419
+ this.client.emit("debug", `WebSocket closed: ${code} - ${reason.toString()}`);
420
+ if (this.pingInterval) clearInterval(this.pingInterval);
421
+ if (!this.isIntentionalClose) {
422
+ this.reconnect();
423
+ }
424
+ });
425
+ this.ws.on("error", (error) => {
426
+ this.client.emit("error", error);
427
+ });
428
+ }
429
+ handleMessage(rawData) {
430
+ const payload = JSON.parse(rawData.toString());
431
+ const eventType = payload.type;
432
+ switch (eventType) {
433
+ case "Error":
434
+ this.client.emit("error", new Error(`Gateway Error: ${payload.error || JSON.stringify(payload)}`));
435
+ break;
436
+ case "Authenticated":
437
+ this.client.emit("debug", "Successfully authenticated with Stoat.");
438
+ break;
439
+ case "Ready": {
440
+ if (payload.channels) {
441
+ for (const rawChannel of payload.channels) {
442
+ this.client.channels._add(rawChannel);
443
+ }
444
+ }
445
+ if (payload.servers) {
446
+ for (const rawServer of payload.servers) {
447
+ this.client.servers._add(rawServer);
448
+ }
449
+ }
450
+ if (payload.users) {
451
+ for (const rawUser of payload.users) {
452
+ this.client.users._add(rawUser);
453
+ if (rawUser.relation === "User" && !this.client.user) {
454
+ this.client.user = new ClientUser(this.client, rawUser);
455
+ }
456
+ }
457
+ }
458
+ this.client.emit("ready", payload);
459
+ break;
460
+ }
461
+ case "Message": {
462
+ if (payload.user) this.client.users._add(payload.user);
463
+ const channel = this.client.channels.cache.get(payload.channel);
464
+ let message;
465
+ if (channel) {
466
+ message = channel.messages._add(payload);
467
+ if ("serverId" in channel) {
468
+ const serverId = channel.serverId;
469
+ const server = this.client.servers.cache.get(serverId);
470
+ if (server && payload.member && payload.user) {
471
+ server.members._add({ ...payload.member, user: payload.user });
472
+ }
473
+ }
474
+ } else {
475
+ message = new Message(this.client, payload);
476
+ }
477
+ this.client.emit("messageCreate", message);
478
+ break;
479
+ }
480
+ case "MessageUpdate": {
481
+ const channel = this.client.channels.cache.get(payload.channel);
482
+ const existing = channel?.messages.cache.get(payload.id);
483
+ if (existing) {
484
+ const oldMessage = existing._clone();
485
+ existing._patch(payload.data);
486
+ this.client.emit("messageUpdate", oldMessage, existing);
487
+ } else {
488
+ const newMessage = new Message(this.client, { id: payload.id, channelId: payload.channel, ...payload.data });
489
+ this.client.emit("messageUpdate", null, newMessage);
490
+ }
491
+ break;
492
+ }
493
+ case "MessageAppend": {
494
+ const channel = this.client.channels.cache.get(payload.channel);
495
+ const message = channel?.messages.cache.get(payload.id);
496
+ if (message && payload.append.embeds) {
497
+ const oldMessage = message._clone();
498
+ message.embeds.push(...payload.append.embeds);
499
+ this.client.emit("messageUpdate", oldMessage, message);
500
+ }
501
+ break;
502
+ }
503
+ case "MessageDelete": {
504
+ const channel = this.client.channels.cache.get(payload.channel);
505
+ let message;
506
+ if (channel) {
507
+ message = channel.messages.cache.get(payload.id);
508
+ channel.messages.cache.delete(payload.id);
509
+ }
510
+ if (message) {
511
+ this.client.emit("messageDelete", message);
512
+ } else {
513
+ this.client.emit("messageDelete", { id: payload.id, channelId: payload.channel });
514
+ }
515
+ break;
516
+ }
517
+ case "Pong":
518
+ this.client.emit("debug", "Received Pong from server.");
519
+ break;
520
+ case "ChannelCreate": {
521
+ const channel = this.client.channels._add(payload);
522
+ this.client.emit("channelCreate", channel);
523
+ break;
524
+ }
525
+ case "ChannelUpdate": {
526
+ const existing = this.client.channels.cache.get(payload.id);
527
+ if (existing) {
528
+ const oldChannel = existing._clone();
529
+ if ("_patch" in existing) {
530
+ existing._patch(payload.data, payload.clear);
531
+ }
532
+ this.client.emit("channelUpdate", oldChannel, existing);
533
+ } else {
534
+ const newChannel = this.client.channels._add({ id: payload.id, ...payload.data });
535
+ this.client.emit("channelUpdate", null, newChannel);
536
+ }
537
+ break;
538
+ }
539
+ case "ChannelDelete": {
540
+ const channel = this.client.channels.cache.get(payload.id);
541
+ if (channel) {
542
+ this.client.channels.cache.delete(channel.id);
543
+ this.client.emit("channelDelete", channel);
544
+ }
545
+ break;
546
+ }
547
+ case "ServerCreate": {
548
+ const server = this.client.servers._add(payload);
549
+ this.client.emit("serverCreate", server);
550
+ break;
551
+ }
552
+ case "ServerUpdate": {
553
+ const existing = this.client.servers.cache.get(payload.id);
554
+ if (existing) {
555
+ const oldServer = existing._clone();
556
+ existing._patch(payload.data, payload.clear);
557
+ this.client.emit("serverUpdate", oldServer, existing);
558
+ } else {
559
+ const newServer = this.client.servers._add({ id: payload.id, ...payload.data });
560
+ this.client.emit("serverUpdate", null, newServer);
561
+ }
562
+ break;
563
+ }
564
+ case "ServerDelete": {
565
+ const server = this.client.servers.cache.get(payload.id);
566
+ if (server) {
567
+ this.client.servers.cache.delete(payload.id);
568
+ this.client.emit("serverDelete", server);
569
+ } else {
570
+ this.client.emit("serverDelete", payload.id);
571
+ }
572
+ break;
573
+ }
574
+ case "ServerMemberJoin": {
575
+ const server = this.client.servers.cache.get(payload.id);
576
+ if (server) {
577
+ const member = server.members._add({ user: payload.user });
578
+ this.client.emit("serverMemberJoin", member);
579
+ }
580
+ break;
581
+ }
582
+ case "ServerMemberLeave": {
583
+ const server = this.client.servers.cache.get(payload.id);
584
+ if (server) {
585
+ const member = server.members.cache.get(payload.user);
586
+ if (member) {
587
+ server.members.cache.delete(payload.user);
588
+ this.client.emit("serverMemberLeave", member);
589
+ }
590
+ }
591
+ break;
592
+ }
593
+ case "UserUpdate": {
594
+ const existing = this.client.users.cache.get(payload.id);
595
+ if (existing) {
596
+ const oldUser = existing._clone();
597
+ existing._patch(payload.data, payload.clear);
598
+ this.client.emit("userUpdate", oldUser, existing);
599
+ }
600
+ break;
601
+ }
602
+ default:
603
+ this.client.emit("raw", payload);
604
+ }
605
+ }
606
+ startPingLoop() {
607
+ if (this.pingInterval) clearInterval(this.pingInterval);
608
+ this.pingInterval = setInterval(() => {
609
+ this.client.emit("debug", "Sending Ping...");
610
+ this.send({ type: "Ping", data: Date.now() });
611
+ }, 2e4);
612
+ }
613
+ send(payload) {
614
+ if (this.ws?.readyState === import_ws.default.OPEN) {
615
+ this.ws.send(JSON.stringify(payload));
616
+ }
617
+ }
618
+ reconnect() {
619
+ if (!this.token) {
620
+ return this.client.emit("error", new Error("RECONNECT_FAILED: No token available."));
621
+ }
622
+ let waitTime = Math.pow(2, this.reconnectAttempts) * 1e3;
623
+ const jitter = waitTime * 0.2 * Math.random();
624
+ waitTime = Math.min(waitTime + jitter, this.maxReconnectWait);
625
+ this.reconnectAttempts++;
626
+ this.client.emit(
627
+ "debug",
628
+ `Attempting to reconnect in ${Math.round(waitTime / 1e3)}s... (Attempt ${this.reconnectAttempts})`
629
+ );
630
+ setTimeout(() => {
631
+ void this.connect(this.token);
632
+ }, waitTime);
633
+ }
634
+ disconnect() {
635
+ this.isIntentionalClose = true;
636
+ if (this.pingInterval) clearInterval(this.pingInterval);
637
+ if (this.ws) {
638
+ this.ws.close(1e3, "Client disconnected gracefully");
639
+ this.ws.removeAllListeners();
640
+ this.ws = null;
641
+ }
642
+ this.client.emit("debug", "Gateway disconnected intentionally.");
643
+ }
644
+ };
645
+
646
+ // src/rest/RESTManager.ts
647
+ var import_undici = require("undici");
648
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
649
+ var AsyncBucket = class {
650
+ remaining = 1;
651
+ resetAt = 0;
652
+ queue = Promise.resolve();
653
+ };
654
+ var RESTManager = class {
655
+ constructor(client) {
656
+ this.client = client;
657
+ }
658
+ baseURL = "https://stoat.chat/api";
659
+ token = null;
660
+ buckets = /* @__PURE__ */ new Map();
661
+ setToken(token) {
662
+ this.token = token;
663
+ }
664
+ /**
665
+ * Generates a local identifier for the bucket based on method and path.
666
+ */
667
+ getRouteKey(method, endpoint) {
668
+ return `${method}:${endpoint}`;
669
+ }
670
+ makeRequest(method, endpoint, body) {
671
+ const routeKey = this.getRouteKey(method, endpoint);
672
+ let bucket = this.buckets.get(routeKey);
673
+ if (!bucket) {
674
+ bucket = new AsyncBucket();
675
+ this.buckets.set(routeKey, bucket);
676
+ }
677
+ return new Promise((resolve, reject) => {
678
+ bucket.queue = bucket.queue.then(async () => {
679
+ try {
680
+ const result = await this.execute(method, endpoint, body, bucket);
681
+ resolve(result);
682
+ } catch (error) {
683
+ reject(error);
684
+ }
685
+ });
686
+ });
687
+ }
688
+ async execute(method, endpoint, body, bucket) {
689
+ if (!this.token) {
690
+ throw new Error("REST_NOT_READY: You must call client.login() before making API requests.");
691
+ }
692
+ const url = `${this.baseURL}${endpoint}`;
693
+ if (bucket.remaining <= 0 && Date.now() < bucket.resetAt) {
694
+ const waitTime = bucket.resetAt - Date.now();
695
+ this.client.emit("debug", `Bucket [${method}:${endpoint}] exhausted. Waiting ${waitTime}ms proactively...`);
696
+ await sleep(waitTime);
697
+ }
698
+ const options = {
699
+ method,
700
+ headers: {
701
+ "X-Bot-Token": this.token,
702
+ "Content-Type": "application/json"
703
+ },
704
+ ...body ? { body: JSON.stringify(body) } : {}
705
+ };
706
+ const response = await (0, import_undici.request)(url, options);
707
+ const remainingHeader = response.headers["x-ratelimit-remaining"];
708
+ const resetAfterHeader = response.headers["x-ratelimit-reset-after"];
709
+ if (remainingHeader !== void 0 && resetAfterHeader !== void 0) {
710
+ bucket.remaining = Number(remainingHeader);
711
+ bucket.resetAt = Date.now() + Number(resetAfterHeader);
712
+ }
713
+ if (response.statusCode === 429) {
714
+ const data2 = await response.body.json();
715
+ const retryMs = data2.retry_after || Number(resetAfterHeader) || 5e3;
716
+ this.client.emit("debug", `Hit 429 on [${method}:${endpoint}]. Retrying in ${retryMs}ms.`);
717
+ bucket.remaining = 0;
718
+ bucket.resetAt = Date.now() + retryMs;
719
+ await sleep(retryMs);
720
+ return this.execute(method, endpoint, body, bucket);
721
+ }
722
+ const data = await response.body.json();
723
+ if (response.statusCode >= 400) {
724
+ let errorMessage = "Unknown Error";
725
+ if (typeof data === "object" && data !== null && "message" in data) {
726
+ errorMessage = String(data.message);
727
+ }
728
+ throw new Error(`[Stoat API Error ${response.statusCode}]: ${errorMessage}`);
729
+ }
730
+ return data;
731
+ }
732
+ /**
733
+ * Uploads a file to Stoat's CDN and returns the File ID
734
+ */
735
+ async uploadFile(filename, fileBuffer) {
736
+ if (!this.token) throw new Error("REST_NOT_READY: No token available.");
737
+ const url = "https://cdn.stoatusercontent.com/attachments";
738
+ const formData = new FormData();
739
+ formData.append("file", new Blob([fileBuffer]), filename);
740
+ const response = await fetch(url, {
741
+ method: "POST",
742
+ headers: {
743
+ "X-Bot-Token": this.token
744
+ },
745
+ body: formData
746
+ });
747
+ if (!response.ok) {
748
+ throw new Error(`Upload failed: ${response.status} ${response.statusText}`);
749
+ }
750
+ const data = await response.json();
751
+ return data.id;
752
+ }
753
+ get(endpoint) {
754
+ return this.makeRequest("GET", endpoint);
755
+ }
756
+ post(endpoint, body) {
757
+ return this.makeRequest("POST", endpoint, body);
758
+ }
759
+ patch(endpoint, body) {
760
+ return this.makeRequest("PATCH", endpoint, body);
761
+ }
762
+ delete(endpoint) {
763
+ return this.makeRequest("DELETE", endpoint);
764
+ }
765
+ async put(endpoint, body) {
766
+ return this.makeRequest("PUT", endpoint, body);
767
+ }
768
+ };
769
+
770
+ // src/utils/Collection.ts
771
+ var Collection = class _Collection extends Map {
772
+ limit;
773
+ constructor(limit = Infinity) {
774
+ super();
775
+ this.limit = limit;
776
+ }
777
+ /**
778
+ * Overrides the default set method to enforce the maximum cache size.
779
+ */
780
+ set(key, value) {
781
+ if (this.limit === 0) return this;
782
+ if (this.size >= this.limit && !this.has(key)) {
783
+ const oldestKey = this.keys().next().value;
784
+ if (oldestKey !== void 0) {
785
+ this.delete(oldestKey);
786
+ }
787
+ }
788
+ return super.set(key, value);
789
+ }
790
+ /**
791
+ * Finds the first item where the given function returns true.
792
+ */
793
+ find(fn) {
794
+ for (const [key, val] of this) {
795
+ if (fn(val, key, this)) return val;
796
+ }
797
+ return void 0;
798
+ }
799
+ /**
800
+ * Returns a new Collection containing only the items where the function returns true.
801
+ */
802
+ filter(fn) {
803
+ const results = new _Collection();
804
+ for (const [key, val] of this) {
805
+ if (fn(val, key, this)) results.set(key, val);
806
+ }
807
+ return results;
808
+ }
809
+ /**
810
+ * Maps each item to a new array of values.
811
+ */
812
+ map(fn) {
813
+ const results = [];
814
+ for (const [key, val] of this) {
815
+ results.push(fn(val, key, this));
816
+ }
817
+ return results;
818
+ }
819
+ /**
820
+ * Gets the very first value in the Collection (based on insertion order).
821
+ */
822
+ first() {
823
+ return this.values().next().value;
824
+ }
825
+ /**
826
+ * Gets the very last value in the Collection.
827
+ */
828
+ last() {
829
+ const arr = Array.from(this.values());
830
+ return arr[arr.length - 1];
831
+ }
832
+ /**
833
+ * Checks if at least one item matches the condition.
834
+ */
835
+ some(fn) {
836
+ for (const [key, val] of this) {
837
+ if (fn(val, key, this)) return true;
838
+ }
839
+ return false;
840
+ }
841
+ };
842
+
843
+ // src/managers/MessageManager.ts
844
+ var util2 = __toESM(require("util"), 1);
845
+
846
+ // src/managers/BaseManager.ts
847
+ var BaseManager = class {
848
+ constructor(client, limit = Infinity) {
849
+ this.client = client;
850
+ this.cache = new Collection(limit);
851
+ }
852
+ cache;
853
+ /**
854
+ * Transforms raw data into a Structure, patches if existing, and saves to cache.
855
+ * @internal
856
+ */
857
+ _add(data) {
858
+ const id = this.extractId(data);
859
+ const existing = this.cache.get(id);
860
+ if (existing && typeof existing._patch === "function") {
861
+ existing._patch(data);
862
+ return existing;
863
+ }
864
+ const structure = this.construct(data);
865
+ this.cache.set(id, structure);
866
+ return structure;
867
+ }
868
+ };
869
+
870
+ // src/managers/MessageManager.ts
871
+ var MessageManager = class extends BaseManager {
872
+ constructor(client, channel, limit = Infinity) {
873
+ super(client, limit);
874
+ this.channel = channel;
875
+ }
876
+ /**
877
+ * Tell BaseManager how to find the ID for Messages
878
+ */
879
+ extractId(data) {
880
+ return data._id ?? data.id;
881
+ }
882
+ /**
883
+ * Tell BaseManager how to build a Message
884
+ */
885
+ construct(data) {
886
+ return new Message(this.client, data);
887
+ }
888
+ async fetch(id) {
889
+ const data = await this.client.rest.get(`/channels/${this.channel.id}/messages/${id}`);
890
+ return this._add(data);
891
+ }
892
+ /**
893
+ * Fetches multiple messages from the channel using specific filter parameters.
894
+ * @param options The query parameters to filter the fetched messages.
895
+ * @returns A promise that resolves to a Collection of fetched Messages.
896
+ * @throws {Error} If the API request fails.
897
+ * @example
898
+ * // Fetch the last 50 messages in the channel
899
+ * const messages = await channel.messages.fetchMany({ limit: 50, sort: "Latest" });
900
+ *
901
+ * // Fetch 20 messages before a specific message ID
902
+ * const history = await channel.messages.fetchMany({ limit: 20, before: "01H..." });
903
+ */
904
+ async fetchMany(options = {}) {
905
+ const params = new URLSearchParams();
906
+ if (options.limit !== void 0) params.append("limit", options.limit.toString());
907
+ if (options.before !== void 0) params.append("before", options.before);
908
+ if (options.after !== void 0) params.append("after", options.after);
909
+ if (options.sort !== void 0) params.append("sort", options.sort);
910
+ if (options.nearby !== void 0) params.append("nearby", options.nearby);
911
+ if (options.includeUsers !== void 0) params.append("include_users", options.includeUsers.toString());
912
+ const queryString = params.toString();
913
+ const endpoint = `/channels/${this.channel.id}/messages${queryString ? `?${queryString}` : ""}`;
914
+ const data = await this.client.rest.get(endpoint);
915
+ const rawMessages = Array.isArray(data) ? data : data.messages || [];
916
+ if (!Array.isArray(data) && data.users) {
917
+ for (const userData of data.users) {
918
+ this.client.users._add(userData);
919
+ }
920
+ }
921
+ const fetched = new Collection();
922
+ for (const rawMsg of rawMessages) {
923
+ const msg = this._add(rawMsg);
924
+ fetched.set(msg.id, msg);
925
+ }
926
+ return fetched;
927
+ }
928
+ resolveId(message) {
929
+ if (typeof message === "string") return message;
930
+ if (message instanceof Message) return message.id;
931
+ throw new Error("Invalid MessageResolvable: must be a Message object or a string ID.");
932
+ }
933
+ /**
934
+ * Sends a new message to this channel.
935
+ * @param contentOrOptions The string content or message options payload.
936
+ * @returns A promise that resolves to the sent Message.
937
+ */
938
+ async send(contentOrOptions) {
939
+ const payload = typeof contentOrOptions === "string" ? { content: contentOrOptions } : { ...contentOrOptions };
940
+ if (payload.embeds) {
941
+ payload.embeds = payload.embeds.map(
942
+ (embed) => typeof embed.toJSON === "function" ? embed.toJSON() : embed
943
+ );
944
+ }
945
+ const data = await this.client.rest.post(`/channels/${this.channel.id}/messages`, payload);
946
+ return new Message(this.client, data);
947
+ }
948
+ /**
949
+ * Edits an existing message.
950
+ * @param message The MessageResolvable (object or ID) to edit.
951
+ * @param contentOrOptions The new content or options.
952
+ * @returns A promise that resolves to the updated Message.
953
+ */
954
+ async edit(message, contentOrOptions) {
955
+ const id = this.resolveId(message);
956
+ const payload = typeof contentOrOptions === "string" ? { content: contentOrOptions } : { ...contentOrOptions };
957
+ if (payload.embeds) {
958
+ payload.embeds = payload.embeds.map(
959
+ (embed) => typeof embed.toJSON === "function" ? embed.toJSON() : embed
960
+ );
961
+ }
962
+ const data = await this.client.rest.patch(`/channels/${this.channel.id}/messages/${id}`, payload);
963
+ const existing = this.cache.get(id);
964
+ if (existing) {
965
+ existing._patch(data);
966
+ return existing;
967
+ }
968
+ return new Message(this.client, data);
969
+ }
970
+ /**
971
+ * Deletes a message from the channel.
972
+ * @param message The MessageResolvable to delete.
973
+ */
974
+ async delete(message) {
975
+ const id = this.resolveId(message);
976
+ await this.client.rest.delete(`/channels/${this.channel.id}/messages/${id}`);
977
+ this.cache.delete(id);
978
+ }
979
+ /**
980
+ * Pins a message in the channel.
981
+ * @param message The MessageResolvable to pin.
982
+ */
983
+ async pin(message) {
984
+ const id = this.resolveId(message);
985
+ await this.client.rest.post(`/channels/${this.channel.id}/messages/${id}/pin`, {});
986
+ const existing = this.cache.get(id);
987
+ if (existing) existing.pinned = true;
988
+ }
989
+ /**
990
+ * Unpins a message in the channel.
991
+ * @param message The MessageResolvable to unpin.
992
+ */
993
+ async unpin(message) {
994
+ const id = this.resolveId(message);
995
+ await this.client.rest.delete(`/channels/${this.channel.id}/messages/${id}/pin`);
996
+ const existing = this.cache.get(id);
997
+ if (existing) existing.pinned = false;
998
+ }
999
+ [util2.inspect.custom]() {
1000
+ return this.cache;
1001
+ }
1002
+ };
1003
+
1004
+ // src/structures/BaseChannel.ts
1005
+ var ChannelType = /* @__PURE__ */ ((ChannelType2) => {
1006
+ ChannelType2["TEXT"] = "TextChannel";
1007
+ ChannelType2["DM"] = "DirectMessage";
1008
+ ChannelType2["GROUP"] = "Group";
1009
+ return ChannelType2;
1010
+ })(ChannelType || {});
1011
+ var BaseChannel = class extends Base {
1012
+ type;
1013
+ messages;
1014
+ constructor(client, data) {
1015
+ super(client, data);
1016
+ this.type = data.channel_type;
1017
+ this.messages = new MessageManager(this.client, this);
1018
+ }
1019
+ /**
1020
+ * Sends a message to this channel.
1021
+ * @param contentOrOptions The string content or message options payload.
1022
+ * @returns A promise that resolves to the sent Message.
1023
+ * @example
1024
+ * await channel.send("Hello world!");
1025
+ * await channel.send({ content: "Here is an embed", embeds: [myEmbed] });
1026
+ */
1027
+ async send(contentOrOptions) {
1028
+ return this.messages.send(contentOrOptions);
1029
+ }
1030
+ async fetch(force = true) {
1031
+ return await this.client.channels.fetch(this.id, force);
1032
+ }
1033
+ /**
1034
+ * Fetches multiple messages from this channel.
1035
+ * @param options The query parameters to filter the messages.
1036
+ */
1037
+ async fetchMessages(options) {
1038
+ return this.messages.fetchMany(options);
1039
+ }
1040
+ /**
1041
+ * Edits this channel.
1042
+ * @param options The fields to update
1043
+ */
1044
+ async edit(options) {
1045
+ return await this.client.channels.edit(this.id, options);
1046
+ }
1047
+ /**
1048
+ * Deletes this channel.
1049
+ */
1050
+ async delete() {
1051
+ await this.client.channels.delete(this.id);
1052
+ }
1053
+ isText() {
1054
+ return this.type === "TextChannel" /* TEXT */;
1055
+ }
1056
+ isDM() {
1057
+ return this.type === "DirectMessage" /* DM */;
1058
+ }
1059
+ isGroup() {
1060
+ return this.type === "Group" /* GROUP */;
1061
+ }
1062
+ };
1063
+
1064
+ // src/structures/TextChannel.ts
1065
+ var TextChannel = class extends BaseChannel {
1066
+ name;
1067
+ serverId;
1068
+ defaultPermissions;
1069
+ description;
1070
+ icon;
1071
+ lastMessageId;
1072
+ nsfw;
1073
+ slowmode;
1074
+ voice;
1075
+ constructor(client, data) {
1076
+ super(client, data);
1077
+ this.serverId = data.server;
1078
+ this.defaultPermissions = data.default_permissions;
1079
+ this.description = data.description;
1080
+ this.icon = data.icon;
1081
+ this.lastMessageId = data.last_message_id;
1082
+ this.nsfw = data.nsfw ?? false;
1083
+ this.slowmode = data.slowmode ?? 0;
1084
+ this.voice = data.voice;
1085
+ this._patch(data);
1086
+ }
1087
+ _patch(data, clear) {
1088
+ if (data.name !== void 0) this.name = data.name;
1089
+ if (data.description !== void 0) this.description = data.description;
1090
+ if (clear && Array.isArray(clear)) {
1091
+ for (const field of clear) {
1092
+ switch (field) {
1093
+ case "Description":
1094
+ this.description = null;
1095
+ break;
1096
+ }
1097
+ }
1098
+ }
1099
+ }
1100
+ /**
1101
+ * Updates the permission overrides for the channel.
1102
+ * @param roleId The raw string ID of the role to update.
1103
+ * @param options The allow and deny permissions to set.
1104
+ * @returns A promise that resolves to the updated BaseChannel.
1105
+ * @throws {TypeError} If the channel is not a Server Channel, or options are invalid.
1106
+ * @throws {Error} If the API request fails.
1107
+ * @example
1108
+ * // Deny a role the ability to send messages in this channel
1109
+ * await channel.setRolePermissions("ROLE_ID", { deny: ["SendMessage"] });
1110
+ */
1111
+ async setRolePermissions(roleId, options) {
1112
+ return await this.client.channels.setRolePermissions(this.id, roleId, options);
1113
+ }
1114
+ /**
1115
+ * Updates the default (everyone) permissions for this channel.
1116
+ * @param permissions The default permissions to grant globally in this channel.
1117
+ * @returns A promise that resolves to the updated BaseChannel.
1118
+ * @throws {TypeError} If invalid permissions are provided.
1119
+ * @throws {Error} If the API request fails.
1120
+ * @example
1121
+ * // Set the default permission to allow everyone to view the channel
1122
+ * await channel.setDefaultPermissions(["ViewChannel", "ReadMessageHistory"]);
1123
+ */
1124
+ async setDefaultPermissions(permissions) {
1125
+ return await this.client.channels.setDefaultPermissions(this.id, permissions);
1126
+ }
1127
+ };
1128
+
1129
+ // src/structures/UnknownChannel.ts
1130
+ var UnknownChannel = class extends BaseChannel {
1131
+ constructor(client, data) {
1132
+ super(client, data);
1133
+ }
1134
+ };
1135
+
1136
+ // src/structures/DMChannel.ts
1137
+ var DMChannel = class extends BaseChannel {
1138
+ active = false;
1139
+ recipients = [];
1140
+ lastMessageId = null;
1141
+ constructor(client, data) {
1142
+ super(client, data);
1143
+ }
1144
+ _patch(data) {
1145
+ if (data.active !== void 0) this.active = data.active;
1146
+ if (data.recipients !== void 0) this.recipients = data.recipients;
1147
+ if (data.last_message_id !== void 0) this.lastMessageId = data.last_message_id;
1148
+ }
1149
+ };
1150
+
1151
+ // src/structures/GroupChannel.ts
1152
+ var util3 = __toESM(require("util"), 1);
1153
+ var GroupChannel = class extends BaseChannel {
1154
+ name;
1155
+ ownerId;
1156
+ recipients = [];
1157
+ description = null;
1158
+ icon = null;
1159
+ lastMessageId = null;
1160
+ nsfw = false;
1161
+ constructor(client, data) {
1162
+ super(client, data);
1163
+ this._patch(data);
1164
+ }
1165
+ _patch(data, clear) {
1166
+ if (data.name !== void 0) this.name = data.name;
1167
+ if (data.owner !== void 0) this.ownerId = data.owner;
1168
+ if (data.recipients !== void 0) this.recipients = data.recipients;
1169
+ if (data.description !== void 0) this.description = data.description;
1170
+ if (data.last_message_id !== void 0) this.lastMessageId = data.last_message_id;
1171
+ if (data.nsfw !== void 0) this.nsfw = data.nsfw;
1172
+ if (data.icon !== void 0) {
1173
+ this.icon = data.icon ? new Attachment(this.client, data.icon) : null;
1174
+ }
1175
+ if (clear && Array.isArray(clear)) {
1176
+ for (const field of clear) {
1177
+ switch (field) {
1178
+ case "Name":
1179
+ this.name = "";
1180
+ break;
1181
+ case "Description":
1182
+ this.description = null;
1183
+ break;
1184
+ case "Icon":
1185
+ this.icon = null;
1186
+ break;
1187
+ }
1188
+ }
1189
+ }
1190
+ }
1191
+ /** Gets the User object of the person who owns this group */
1192
+ get owner() {
1193
+ return this.client.users.cache.get(this.ownerId);
1194
+ }
1195
+ /** Resolves the recipient IDs into an array of cached User objects */
1196
+ get recipientUsers() {
1197
+ return this.recipients.map((id) => this.client.users.cache.get(id)).filter((user) => user !== void 0);
1198
+ }
1199
+ /**
1200
+ * Updates the default (everyone) permissions for this channel.
1201
+ * @param permissions The default permissions to grant globally in this channel.
1202
+ * @returns A promise that resolves to the updated BaseChannel.
1203
+ * @throws {TypeError} If invalid permissions are provided.
1204
+ * @throws {Error} If the API request fails.
1205
+ * @example
1206
+ * // Set the default permission to allow everyone to view the channel
1207
+ * await channel.setDefaultPermissions(["ViewChannel", "ReadMessageHistory"]);
1208
+ */
1209
+ async setDefaultPermissions(permissions) {
1210
+ return await this.client.channels.setDefaultPermissions(this.id, permissions);
1211
+ }
1212
+ [util3.inspect.custom](_depth, options, inspect10) {
1213
+ const { client, ...props } = this;
1214
+ return `${this.constructor.name} ${inspect10(
1215
+ {
1216
+ ...props,
1217
+ owner: this.owner,
1218
+ recipientUsers: this.recipientUsers
1219
+ },
1220
+ options
1221
+ )}`;
1222
+ }
1223
+ };
1224
+
1225
+ // src/utils/ChannelFactory.ts
1226
+ function createChannel(client, data) {
1227
+ switch (data.channel_type) {
1228
+ case "TextChannel" /* TEXT */:
1229
+ return new TextChannel(client, data);
1230
+ case "DirectMessage" /* DM */:
1231
+ return new DMChannel(client, data);
1232
+ case "Group" /* GROUP */:
1233
+ return new GroupChannel(client, data);
1234
+ default:
1235
+ client.emit("debug", `Received unknown channel type: ${data.type}`);
1236
+ return new UnknownChannel(client, data);
1237
+ }
1238
+ }
1239
+
1240
+ // src/utils/permissions.ts
1241
+ var PermissionFlags = {
1242
+ // Server permissions
1243
+ ManageChannel: 1n << 0n,
1244
+ ManageServer: 1n << 1n,
1245
+ ManagePermissions: 1n << 2n,
1246
+ ManageRole: 1n << 3n,
1247
+ ManageCustomisation: 1n << 4n,
1248
+ // Member permissions
1249
+ KickMembers: 1n << 6n,
1250
+ BanMembers: 1n << 7n,
1251
+ TimeoutMembers: 1n << 8n,
1252
+ AssignRoles: 1n << 9n,
1253
+ ChangeNickname: 1n << 10n,
1254
+ ManageNicknames: 1n << 11n,
1255
+ ChangeAvatar: 1n << 12n,
1256
+ RemoveAvatars: 1n << 13n,
1257
+ // Channel permissions
1258
+ ViewChannel: 1n << 20n,
1259
+ ReadMessageHistory: 1n << 21n,
1260
+ SendMessage: 1n << 22n,
1261
+ ManageMessages: 1n << 23n,
1262
+ ManageWebhooks: 1n << 24n,
1263
+ InviteOthers: 1n << 25n,
1264
+ SendEmbeds: 1n << 26n,
1265
+ UploadFiles: 1n << 27n,
1266
+ Masquerade: 1n << 28n,
1267
+ React: 1n << 29n,
1268
+ BypassSlowmode: 1n << 39n,
1269
+ // Voice permissions
1270
+ Connect: 1n << 30n,
1271
+ Speak: 1n << 31n,
1272
+ Video: 1n << 32n,
1273
+ MuteMembers: 1n << 33n,
1274
+ DeafenMembers: 1n << 34n,
1275
+ MoveMembers: 1n << 35n,
1276
+ Listen: 1n << 36n,
1277
+ // Channel permissions (Part 2)
1278
+ MentionEveryone: 1n << 37n,
1279
+ MentionRoles: 1n << 38n,
1280
+ // Grant all
1281
+ GrantAllSafe: 0x000fffffffffffffn
1282
+ };
1283
+ var Permissions = class {
1284
+ /**
1285
+ * Converts a string, BigInt, or array of strings into a single BigInt
1286
+ */
1287
+ static resolve(permission) {
1288
+ if (typeof permission === "bigint") return permission;
1289
+ if (typeof permission === "string") {
1290
+ return PermissionFlags[permission] ?? 0n;
1291
+ }
1292
+ if (Array.isArray(permission)) {
1293
+ return permission.reduce((acc, p) => acc | this.resolve(p), 0n);
1294
+ }
1295
+ return 0n;
1296
+ }
1297
+ /**
1298
+ * Checks if a specific permission bit exists
1299
+ */
1300
+ static has(totalPermissions, permissionToCheck) {
1301
+ const resolvedCheck = this.resolve(permissionToCheck);
1302
+ return (totalPermissions & resolvedCheck) === resolvedCheck;
1303
+ }
1304
+ };
1305
+
1306
+ // src/managers/ChannelManager.ts
1307
+ var ChannelManager = class extends BaseManager {
1308
+ /**
1309
+ * Manages API methods and caching for all channels globally.
1310
+ * @param client The active Client instance.
1311
+ * @param limit The maximum number of channels to hold in the cache.
1312
+ */
1313
+ constructor(client, limit = Infinity) {
1314
+ super(client, limit);
1315
+ this.client = client;
1316
+ }
1317
+ extractId(data) {
1318
+ return data._id ?? data.id;
1319
+ }
1320
+ construct(data) {
1321
+ return createChannel(this.client, data);
1322
+ }
1323
+ /**
1324
+ * Resolves a ChannelResolvable to a cached BaseChannel object.
1325
+ * @param channel The ChannelResolvable to resolve.
1326
+ * @returns The resolved BaseChannel, or undefined if not cached.
1327
+ */
1328
+ resolve(channel) {
1329
+ if (channel instanceof BaseChannel) return channel;
1330
+ if (typeof channel === "string") {
1331
+ const id = channel.replace(/[<#>]/g, "");
1332
+ return this.cache.get(id);
1333
+ }
1334
+ return void 0;
1335
+ }
1336
+ resolveText(channel) {
1337
+ const resolved = this.resolve(channel);
1338
+ return resolved?.isText() ? resolved : void 0;
1339
+ }
1340
+ resolveDM(channel) {
1341
+ const resolved = this.resolve(channel);
1342
+ return resolved?.isDM() ? resolved : void 0;
1343
+ }
1344
+ resolveGroup(channel) {
1345
+ const resolved = this.resolve(channel);
1346
+ return resolved?.isGroup() ? resolved : void 0;
1347
+ }
1348
+ /**
1349
+ * Extracts ID from a ChannelResolvable.
1350
+ * @param channel The ChannelResolvable to extract the ID from.
1351
+ * @returns The extracted channel ID.
1352
+ * @throws {TypeError} If an invalid type is provided.
1353
+ */
1354
+ resolveId(channel) {
1355
+ if (channel instanceof BaseChannel) {
1356
+ return channel.id;
1357
+ }
1358
+ if (typeof channel === "string") {
1359
+ return channel.replace(/[<#>]/g, "");
1360
+ }
1361
+ throw new TypeError("Invalid ChannelResolvable provided. Expected a BaseChannel object or a string ID/Mention.");
1362
+ }
1363
+ /**
1364
+ * Fetches a Channel from the API or resolves it from the local cache.
1365
+ * @param channel The ID, mention, or Channel object to fetch.
1366
+ * @param force Whether to skip the cache check and force a direct API request. Defaults to true.
1367
+ * @returns A promise that resolves to the fetched BaseChannel object.
1368
+ * @throws {TypeError} If an invalid ChannelResolvable is provided.
1369
+ * @throws {Error} If the API request fails.
1370
+ * @example
1371
+ * // Fetch a channel, bypassing cache
1372
+ * const channel = await client.channels.fetch("01H...");
1373
+ */
1374
+ async fetch(channel, force = true) {
1375
+ if (!force) {
1376
+ const cached = this.resolve(channel);
1377
+ if (cached) return cached;
1378
+ }
1379
+ const id = this.resolveId(channel);
1380
+ const data = await this.client.rest.get(`/channels/${id}`);
1381
+ return this._add(data);
1382
+ }
1383
+ /**
1384
+ * Edits a channel in the server.
1385
+ * @param channel The ChannelResolvable to edit.
1386
+ * @param options The fields to update.
1387
+ * @returns A promise that resolves to the updated BaseChannel.
1388
+ * @throws {TypeError} If invalid options or ChannelResolvable are provided.
1389
+ * @throws {Error} If the API request fails.
1390
+ * @example
1391
+ * // Update channel name and remove its description
1392
+ * await client.channels.edit("01H...", { name: "general", description: null });
1393
+ */
1394
+ async edit(channel, options) {
1395
+ if (!options || typeof options !== "object") {
1396
+ throw new TypeError("ChannelEditOptions must be a valid object.");
1397
+ }
1398
+ const payload = {};
1399
+ const remove = [];
1400
+ if (options.name !== void 0) payload.name = options.name;
1401
+ if (options.owner !== void 0) payload.owner = options.owner;
1402
+ if (options.nsfw !== void 0) payload.nsfw = options.nsfw;
1403
+ if (options.archived !== void 0) payload.archived = options.archived;
1404
+ if (options.voice !== void 0) payload.voice = options.voice;
1405
+ if (options.slowmode !== void 0) payload.slowmode = options.slowmode;
1406
+ if (options.description !== void 0) {
1407
+ if (options.description === null) remove.push("Description");
1408
+ else payload.description = options.description;
1409
+ }
1410
+ if (options.icon !== void 0) {
1411
+ if (options.icon === null) remove.push("Icon");
1412
+ else payload.icon = options.icon;
1413
+ }
1414
+ if (remove.length > 0) payload.remove = remove;
1415
+ if (Object.keys(payload).length === 0) return this.fetch(channel);
1416
+ const data = await this.client.rest.patch(`/channels/${this.resolveId(channel)}`, payload);
1417
+ return this._add(data);
1418
+ }
1419
+ /**
1420
+ * Updates the permission overrides for a specific role in a channel.
1421
+ * @param channel The ChannelResolvable to update permissions for.
1422
+ * @param roleId The raw string ID of the role to update.
1423
+ * @param options The allow and deny permissions to set.
1424
+ * @returns A promise that resolves to the updated BaseChannel.
1425
+ * @throws {TypeError} If the channel is not a Server Channel, or options are invalid.
1426
+ * @throws {Error} If the API request fails.
1427
+ * @example
1428
+ * // Deny a role the ability to send messages in this channel
1429
+ * await client.channels.setRolePermissions(channel, "ROLE_ID", { deny: ["SendMessage"] });
1430
+ */
1431
+ async setRolePermissions(channel, roleId, options) {
1432
+ const resolved = this.resolve(channel);
1433
+ if (resolved && !resolved.isText()) {
1434
+ throw new TypeError("Role permissions can only be set on Server Channels.");
1435
+ }
1436
+ if (!options || typeof options !== "object") {
1437
+ throw new TypeError("ChannelRolePermissionOptions must be a valid object.");
1438
+ }
1439
+ const id = this.resolveId(channel);
1440
+ const allowBigInt = options.allow !== void 0 ? Permissions.resolve(options.allow) : 0n;
1441
+ const denyBigInt = options.deny !== void 0 ? Permissions.resolve(options.deny) : 0n;
1442
+ const payload = {
1443
+ permissions: {
1444
+ allow: Number(allowBigInt),
1445
+ deny: Number(denyBigInt)
1446
+ }
1447
+ };
1448
+ const data = await this.client.rest.put(`/channels/${id}/permissions/${roleId}`, payload);
1449
+ return this._add(data);
1450
+ }
1451
+ /**
1452
+ * Updates the default (everyone) permissions for a channel.
1453
+ * @param channel The ChannelResolvable to update permissions for.
1454
+ * @param permissions The default permissions to grant globally in this channel.
1455
+ * @returns A promise that resolves to the updated BaseChannel.
1456
+ * @throws {TypeError} If invalid permissions are provided.
1457
+ * @throws {Error} If the API request fails.
1458
+ * @example
1459
+ * // Set the default permission to allow everyone to view the channel
1460
+ * await client.channels.setDefaultPermissions(channel, ["ViewChannel", "ReadMessageHistory"]);
1461
+ */
1462
+ async setDefaultPermissions(channel, permissions) {
1463
+ const resolved = this.resolve(channel);
1464
+ if (resolved && resolved.isDM()) {
1465
+ throw new TypeError("Default permissions cannot be set on Direct Message channels.");
1466
+ }
1467
+ const id = this.resolveId(channel);
1468
+ const permBigInt = Permissions.resolve(permissions);
1469
+ const payload = {
1470
+ permissions: Number(permBigInt)
1471
+ };
1472
+ const data = await this.client.rest.put(`/channels/${id}/permissions/default`, payload);
1473
+ return this._add(data);
1474
+ }
1475
+ /**
1476
+ * Deletes a server channel, leaves a group, or closes a DM.
1477
+ * @param channel The channel object, raw ID, or mention string to delete.
1478
+ * @returns A promise that resolves when the action is successful.
1479
+ * @throws {Error} If the API request fails.
1480
+ * @example
1481
+ * await client.channels.delete("01H...");
1482
+ */
1483
+ async delete(channel) {
1484
+ const id = this.resolveId(channel);
1485
+ await this.client.rest.delete(`/channels/${id}`);
1486
+ this.cache.delete(id);
1487
+ }
1488
+ };
1489
+
1490
+ // src/structures/Member.ts
1491
+ var util4 = __toESM(require("util"), 1);
1492
+
1493
+ // src/managers/MemberRoleManager.ts
1494
+ var MemberRoleManager = class {
1495
+ constructor(member) {
1496
+ this.member = member;
1497
+ }
1498
+ /**
1499
+ * Gets a Collection of the actual Role objects this member has.
1500
+ * This dynamically pulls from the Server's role cache so references are always up to date
1501
+ */
1502
+ get cache() {
1503
+ const fetched = new Collection();
1504
+ const server = this.member.server;
1505
+ if (!server) return fetched;
1506
+ for (const roleId of this.member.roleIds) {
1507
+ const role = server.roles.cache.get(roleId);
1508
+ if (role) fetched.set(role.id, role);
1509
+ }
1510
+ return fetched;
1511
+ }
1512
+ /**
1513
+ * Checks if the member has a specific role.
1514
+ * @param role The RoleResolvable to check for.
1515
+ */
1516
+ has(role) {
1517
+ const server = this.member.server;
1518
+ if (!server) return false;
1519
+ const id = server.roles.resolveId(role);
1520
+ return this.member.roleIds.includes(id);
1521
+ }
1522
+ /**
1523
+ * Adds a role to the member.
1524
+ * @param role The RoleResolvable to add.
1525
+ * @returns A promise that resolves to the updated Member.
1526
+ */
1527
+ async add(role) {
1528
+ const server = this.member.server;
1529
+ if (!server) throw new Error("Server not cached, cannot add role.");
1530
+ const id = server.roles.resolveId(role);
1531
+ if (this.member.roleIds.includes(id)) return this.member;
1532
+ const newRoles = [...this.member.roleIds, id];
1533
+ return this.member.edit({ roles: newRoles });
1534
+ }
1535
+ /**
1536
+ * Removes a role from the member.
1537
+ * @param role The RoleResolvable to remove.
1538
+ * @returns A promise that resolves to the updated Member.
1539
+ */
1540
+ async remove(role) {
1541
+ const server = this.member.server;
1542
+ if (!server) throw new Error("Server not cached, cannot remove role.");
1543
+ const id = server.roles.resolveId(role);
1544
+ if (!this.member.roleIds.includes(id)) return this.member;
1545
+ const newRoles = this.member.roleIds.filter((rId) => rId !== id);
1546
+ return this.member.edit({ roles: newRoles });
1547
+ }
1548
+ /**
1549
+ * Overwrites all roles on the member with a completely new array.
1550
+ * @param roles An array of RoleResolvables.
1551
+ * @returns A promise that resolves to the updated Member.
1552
+ */
1553
+ async set(roles) {
1554
+ const server = this.member.server;
1555
+ if (!server) throw new Error("Server not cached, cannot set roles.");
1556
+ const newRoles = roles.map((r) => server.roles.resolveId(r));
1557
+ return this.member.edit({ roles: newRoles });
1558
+ }
1559
+ };
1560
+
1561
+ // src/structures/Member.ts
1562
+ var Member = class extends Base {
1563
+ serverId;
1564
+ nickname = null;
1565
+ avatar = null;
1566
+ roleIds = [];
1567
+ joinedAt;
1568
+ timeout = null;
1569
+ canPublish = false;
1570
+ canRecieve = false;
1571
+ roles;
1572
+ constructor(client, data) {
1573
+ super(client, { _id: data.user._id });
1574
+ this.serverId = data.serverId || data.server_id;
1575
+ this.joinedAt = new Date(data.joinedAt || data.joined_at);
1576
+ this.roles = new MemberRoleManager(this);
1577
+ this._patch(data);
1578
+ }
1579
+ _patch(data) {
1580
+ if (data.nickname !== void 0) this.nickname = data.nickname;
1581
+ if (data.avatar !== void 0) this.avatar = data.avatar;
1582
+ if (data.roles !== void 0) this.roleIds = data.roles;
1583
+ if (data.timeout !== void 0) this.timeout = data.timeout ? new Date(data.timeout) : null;
1584
+ if (data.can_publish !== void 0) this.canPublish = data.canPublish;
1585
+ if (data.can_recieve !== void 0) this.canRecieve = data.canRecieve;
1586
+ }
1587
+ /** Gets the global User object for this member */
1588
+ get user() {
1589
+ return this.client.users.cache.get(this.id);
1590
+ }
1591
+ /** Gets the Server object this member belongs to */
1592
+ get server() {
1593
+ return this.client.servers.cache.get(this.serverId);
1594
+ }
1595
+ /** Resolves the array of role strings into actual Role objects */
1596
+ get roleObjects() {
1597
+ const server = this.server;
1598
+ if (!server) return [];
1599
+ return this.roleIds.map((id) => server.roles.cache.get(id)).filter((role) => role !== void 0);
1600
+ }
1601
+ /** Calculates the member's total permissions using BigInt */
1602
+ get permissions() {
1603
+ const server = this.server;
1604
+ if (!server) return 0n;
1605
+ let totalPerms = server.defaultPermissions ?? 0n;
1606
+ for (const role of this.roleObjects) {
1607
+ totalPerms |= BigInt(role.permissions);
1608
+ }
1609
+ if (server.ownerId === this.id) {
1610
+ return PermissionFlags.GrantAllSafe;
1611
+ }
1612
+ return totalPerms;
1613
+ }
1614
+ /** Checks if the member has a specific permission */
1615
+ hasPermission(permission) {
1616
+ return Permissions.has(this.permissions, permission);
1617
+ }
1618
+ /**
1619
+ * Edits this member's nickname, avatar, roles, or timeout.
1620
+ */
1621
+ async edit(options) {
1622
+ let server = this.server;
1623
+ if (!server) server = await this.client.servers.fetch(this.serverId);
1624
+ return await server.members.edit(this.id, options);
1625
+ }
1626
+ /**
1627
+ * Kicks this member from the server.
1628
+ */
1629
+ async kick() {
1630
+ let server = this.server;
1631
+ if (!server) server = await this.client.servers.fetch(this.serverId);
1632
+ await server.members.kick(this.id);
1633
+ }
1634
+ /**
1635
+ * Bans this member from the server.
1636
+ * @param options The options for this ban
1637
+ */
1638
+ async ban(options) {
1639
+ let server = this.server;
1640
+ if (!server) server = await this.client.servers.fetch(this.serverId);
1641
+ await server.members.ban(this.id, options);
1642
+ }
1643
+ async unban() {
1644
+ let server = this.client.servers.cache.get(this.serverId);
1645
+ if (!server) server = await this.client.servers.fetch(this.serverId);
1646
+ await server.members.unban(this.id);
1647
+ }
1648
+ [util4.inspect.custom](depth, options, inspect10) {
1649
+ const { client, serverId, ...props } = this;
1650
+ return `${this.constructor.name} ${inspect10(
1651
+ {
1652
+ ...props,
1653
+ user: this.user,
1654
+ permissions: this.permissions
1655
+ },
1656
+ { ...options, depth: depth ?? options.depth }
1657
+ )}`;
1658
+ }
1659
+ };
1660
+
1661
+ // src/managers/MemberManager.ts
1662
+ var util5 = __toESM(require("util"), 1);
1663
+ var MemberManager = class extends BaseManager {
1664
+ constructor(client, server, limit = Infinity) {
1665
+ super(client, limit);
1666
+ this.server = server;
1667
+ }
1668
+ /**
1669
+ * Tell BaseManager how to handle Revolt's Member IDs
1670
+ * @internal
1671
+ */
1672
+ extractId(data) {
1673
+ return data.user_id ?? data.id ?? (typeof data._id === "string" ? data._id : data._id?.user);
1674
+ }
1675
+ /**
1676
+ * Tell BaseManager how to build a Member
1677
+ * @internal
1678
+ */
1679
+ construct(data) {
1680
+ if (!data.server_id && !data.serverId) {
1681
+ data.serverId = this.server.id;
1682
+ }
1683
+ return new Member(this.client, data);
1684
+ }
1685
+ resolve(member) {
1686
+ if (member instanceof Member) return member;
1687
+ if (member instanceof User) return this.cache.get(member.id);
1688
+ if (typeof member === "string") return this.cache.get(member.replace(/[<@>]/g, ""));
1689
+ return void 0;
1690
+ }
1691
+ resolveId(member) {
1692
+ if (typeof member === "string") return member.replace(/[<@>]/g, "");
1693
+ if ("id" in member) return member.id;
1694
+ throw new TypeError("Invalid MemberResolvable provided.");
1695
+ }
1696
+ async fetch(member, force = true) {
1697
+ if (!force) {
1698
+ const cached = this.resolve(member);
1699
+ if (cached) return cached;
1700
+ }
1701
+ const id = this.resolveId(member);
1702
+ const data = await this.client.rest.get(`/channels/${id}`);
1703
+ return this._add(data);
1704
+ }
1705
+ /**
1706
+ * Fetches multiple members from the server.
1707
+ * @param options Filter options for the fetch request.
1708
+ * @returns A promise that resolves to a Collection of fetched Members.
1709
+ * @throws {Error} If the API request fails.
1710
+ * @example
1711
+ * // Fetch all members in the server
1712
+ * const allMembers = await server.members.fetchMany();
1713
+ *
1714
+ * // Fetch only online members to save bandwidth
1715
+ * const onlineMembers = await server.members.fetchMany({ exclude_offline: true });
1716
+ */
1717
+ async fetchMany(options = {}) {
1718
+ const params = new URLSearchParams();
1719
+ if (options.exclude_offline !== void 0) {
1720
+ params.append("exclude_offline", options.exclude_offline.toString());
1721
+ }
1722
+ const queryString = params.toString();
1723
+ const endpoint = `/servers/${this.server.id}/members${queryString ? `?${queryString}` : ""}`;
1724
+ const data = await this.client.rest.get(endpoint);
1725
+ if (data.users && Array.isArray(data.users)) {
1726
+ for (const userData of data.users) {
1727
+ this.client.users._add(userData);
1728
+ }
1729
+ }
1730
+ const fetched = new Collection();
1731
+ const rawMembers = data.members || (Array.isArray(data) ? data : []);
1732
+ for (const rawMember of rawMembers) {
1733
+ const member = this._add(rawMember);
1734
+ fetched.set(member.id, member);
1735
+ }
1736
+ return fetched;
1737
+ }
1738
+ /**
1739
+ * Edits a member in the server.
1740
+ * @param member The MemberResolvable to edit.
1741
+ * @param options The fields to update (nickname, roles, timeout, etc.).
1742
+ */
1743
+ async edit(member, options) {
1744
+ const id = this.resolveId(member);
1745
+ const payload = {};
1746
+ const remove = [];
1747
+ if (options.nickname !== void 0) {
1748
+ if (options.nickname === null) remove.push("Nickname");
1749
+ else payload.nickname = options.nickname;
1750
+ }
1751
+ if (options.avatar !== void 0) {
1752
+ if (options.avatar === null) remove.push("Avatar");
1753
+ else payload.avatar = options.avatar;
1754
+ }
1755
+ if (options.roles !== void 0) payload.roles = options.roles;
1756
+ if (options.timeout !== void 0) {
1757
+ if (options.timeout === null) remove.push("Timeout");
1758
+ else payload.timeout = options.timeout;
1759
+ }
1760
+ if (remove.length > 0) payload.remove = remove;
1761
+ if (Object.keys(payload).length === 0) return this.fetch(id);
1762
+ const data = await this.client.rest.patch(`/servers/${this.server.id}/members/${id}`, payload);
1763
+ return this._add(data);
1764
+ }
1765
+ /**
1766
+ * Kicks a member from the server.
1767
+ * @param member The MemberResolvable to kick.
1768
+ */
1769
+ async kick(member) {
1770
+ const id = this.resolveId(member);
1771
+ await this.client.rest.delete(`/servers/${this.server.id}/members/${id}`);
1772
+ this.cache.delete(id);
1773
+ }
1774
+ /**
1775
+ * Bans a member from the server.
1776
+ * @param member The MemberResolvable to ban.
1777
+ * @param options The ban options
1778
+ */
1779
+ async ban(member, options) {
1780
+ const id = this.resolveId(member);
1781
+ const payload = {};
1782
+ if (options?.reason !== void 0) payload.reason = options.reason;
1783
+ if (options?.deleteMessageSeconds !== void 0) payload.delete_message_seconds = options.deleteMessageSeconds;
1784
+ await this.client.rest.put(`/servers/${this.server.id}/bans/${id}`, payload);
1785
+ this.cache.delete(id);
1786
+ }
1787
+ /**
1788
+ * Unbans a user from the server
1789
+ * @param member The MemberResolvable to unban
1790
+ */
1791
+ async unban(member) {
1792
+ const id = this.resolveId(member);
1793
+ await this.client.rest.delete(`/servers/${this.server.id}/bans/${id}`);
1794
+ }
1795
+ [util5.inspect.custom]() {
1796
+ return this.cache;
1797
+ }
1798
+ };
1799
+
1800
+ // src/managers/ServerChannelManager.ts
1801
+ var util6 = __toESM(require("util"), 1);
1802
+ var ServerChannelManager = class {
1803
+ constructor(client, server) {
1804
+ this.client = client;
1805
+ this.server = server;
1806
+ }
1807
+ get cache() {
1808
+ return this.client.channels.cache.filter((channel) => channel.serverId === this.server.id);
1809
+ }
1810
+ /**
1811
+ * Creates a new channel within this server.
1812
+ * @param options The configuration for the new channel.
1813
+ * @returns The newly created Channel object.
1814
+ */
1815
+ async create(options) {
1816
+ if (!options.name) throw new Error("A channel name must be provided.");
1817
+ const payload = {
1818
+ name: options.name,
1819
+ type: options.type ?? "Text",
1820
+ description: options.description,
1821
+ nsfw: options.nsfw ?? false
1822
+ };
1823
+ if (options.type === "Voice" && options.voice?.max_users) {
1824
+ payload.voice = { max_users: options.voice.max_users };
1825
+ }
1826
+ const data = await this.client.rest.post(`/servers/${this.server.id}/channels`, payload);
1827
+ return this.client.channels._add(data);
1828
+ }
1829
+ [util6.inspect.custom]() {
1830
+ return this.cache;
1831
+ }
1832
+ };
1833
+
1834
+ // src/structures/Role.ts
1835
+ var util7 = __toESM(require("util"), 1);
1836
+ var Role = class extends Base {
1837
+ serverId;
1838
+ name;
1839
+ color = null;
1840
+ hoist = false;
1841
+ rank = 0;
1842
+ permissions = 0n;
1843
+ constructor(client, data, serverId) {
1844
+ super(client, data);
1845
+ this.serverId = serverId;
1846
+ this._patch(data);
1847
+ }
1848
+ /**
1849
+ * Updates the role instance with new data without losing the object reference.
1850
+ * @internal
1851
+ */
1852
+ _patch(data) {
1853
+ if (data.name !== void 0) this.name = data.name;
1854
+ if (data.color !== void 0) this.color = data.color;
1855
+ if (data.hoist !== void 0) this.hoist = data.hoist;
1856
+ if (data.rank !== void 0) this.rank = data.rank;
1857
+ if (data.permissions !== void 0) {
1858
+ try {
1859
+ if (typeof data.permissions === "object" && data.permissions !== null) {
1860
+ const allowPerms = data.permissions.a ?? data.permissions[0] ?? 0;
1861
+ this.permissions = BigInt(allowPerms);
1862
+ } else {
1863
+ this.permissions = BigInt(data.permissions);
1864
+ }
1865
+ } catch {
1866
+ this.permissions = 0n;
1867
+ }
1868
+ }
1869
+ }
1870
+ /**
1871
+ * The server this role belongs to.
1872
+ * Pulls dynamically from the cache to prevent massive memory duplication.
1873
+ */
1874
+ get server() {
1875
+ return this.client.servers.cache.get(this.serverId);
1876
+ }
1877
+ /**
1878
+ * Checks whether this role has a specific permission.
1879
+ * @param permission The permission to check for.
1880
+ * @returns True if the role has the permission.
1881
+ */
1882
+ hasPermission(permission) {
1883
+ return Permissions.has(this.permissions, permission);
1884
+ }
1885
+ /**
1886
+ * Fetches this role directly from the API to ensure data is up to date.
1887
+ * @param force Whether to skip the cache check and force a direct API request. Defaults to false.
1888
+ * @returns A promise that resolves to the fetched Role object.
1889
+ * @throws {TypeError} If an invalid RoleResolvable is provided.
1890
+ * @throws {Error} If the API request fails (e.g., the role does not exist).
1891
+ * @example
1892
+ * // Refresh the role's data from the API
1893
+ * await role.fetch();
1894
+ * console.log(`Role updated, current name: ${role.name}`);
1895
+ */
1896
+ async fetch(force = true) {
1897
+ let server = this.server;
1898
+ if (!server) {
1899
+ server = await this.client.servers.fetch(this.serverId);
1900
+ }
1901
+ return await server.roles.fetch(this.id, force);
1902
+ }
1903
+ /**
1904
+ * Edits the role with the given options. Only the fields provided in the options will be updated; all other fields will remain unchanged.
1905
+ * @param options The fields to update.
1906
+ * @returns A promise that resolves to the updated Role.
1907
+ * @throws {TypeError} If invalid options or RoleResolvable are provided.
1908
+ * @throws {Error} If the API request fails (e.g., lack of permissions).
1909
+ * @example
1910
+ * // Change the role's name and color
1911
+ * await role.edit({ name: "Senior Admin", colour: "#FFD700" });
1912
+ *
1913
+ * // Remove the custom color from the role
1914
+ * await role.edit({ colour: null });
1915
+ */
1916
+ async edit(options) {
1917
+ let server = this.server;
1918
+ if (!server) server = await this.client.servers.fetch(this.serverId);
1919
+ return await server.roles.edit(this.id, options);
1920
+ }
1921
+ /**
1922
+ * Deletes this Role from the server.
1923
+ * @throws {Error} If the role cannot be deleted (e.g., lack of permissions).
1924
+ * @example
1925
+ * // Delete a role by its ID
1926
+ * await role.delete();
1927
+ */
1928
+ async delete() {
1929
+ let server = this.server;
1930
+ if (!server) {
1931
+ server = await this.client.servers.fetch(this.serverId);
1932
+ }
1933
+ await server.roles.delete(this.id);
1934
+ }
1935
+ /**
1936
+ * Updates the permissions for this role.
1937
+ * @param options The allow and deny permissions to set.
1938
+ * @returns A promise that resolves to the updated Role object.
1939
+ * @throws {TypeError} If invalid options are provided.
1940
+ * @throws {Error} If the API request fails.
1941
+ * @example
1942
+ * // Grant the role permission to manage channels and send messages
1943
+ * await role.setPermissions({
1944
+ * allow: ["ManageChannel", "SendMessage"]
1945
+ * });
1946
+ */
1947
+ async setPermissions(options) {
1948
+ let server = this.server;
1949
+ if (!server) server = await this.client.servers.fetch(this.serverId);
1950
+ return await server.roles.setPermissions(this.id, options);
1951
+ }
1952
+ /**
1953
+ * Updates the hierarchical position of this role.
1954
+ * Automatically reconstructs the role array and performs a bulk update.
1955
+ * @param newPosition The new rank/position for this role (0-indexed).
1956
+ * @returns A promise that resolves to this updated Role object.
1957
+ * @throws {Error} If API request fails.
1958
+ * @example
1959
+ * // Move this role to position 2 in the hierarchy
1960
+ * await role.setPosition(2);
1961
+ * console.log(`Role moved to rank: ${role.rank}`);
1962
+ */
1963
+ async setPosition(newPosition) {
1964
+ let server = this.server;
1965
+ if (!server) server = await this.client.servers.fetch(this.serverId);
1966
+ const sortedRoles = Array.from(server.roles.cache.values()).sort((a, b) => a.rank - b.rank);
1967
+ const filteredRoles = sortedRoles.filter((r) => r.id !== this.id);
1968
+ const clampedPosition = Math.max(0, Math.min(newPosition, filteredRoles.length));
1969
+ filteredRoles.splice(clampedPosition, 0, this);
1970
+ await server.roles.setRanks(filteredRoles);
1971
+ return this;
1972
+ }
1973
+ /**
1974
+ * Customizer for Node.js `console.log` and `util.inspect`.
1975
+ * Hides the cyclic client reference and raw serverId for a cleaner output.
1976
+ * @internal
1977
+ */
1978
+ [util7.inspect.custom]() {
1979
+ const { client, serverId, ...props } = this;
1980
+ return `${this.constructor.name} ${util7.inspect(props)}`;
1981
+ }
1982
+ };
1983
+
1984
+ // src/managers/RoleManager.ts
1985
+ var util8 = __toESM(require("util"), 1);
1986
+ var RoleManager = class extends BaseManager {
1987
+ /**
1988
+ * Manages API methods and caching for server roles.
1989
+ */
1990
+ constructor(client, server, limit = Infinity) {
1991
+ super(client, limit);
1992
+ this.server = server;
1993
+ }
1994
+ /**
1995
+ * Tell BaseManager how to find the ID for Roles
1996
+ */
1997
+ extractId(data) {
1998
+ return data._id ?? data.id;
1999
+ }
2000
+ /**
2001
+ * Tell BaseManager how to build a Role
2002
+ */
2003
+ construct(data) {
2004
+ return new Role(this.client, data, this.server.id);
2005
+ }
2006
+ /**
2007
+ * Adds or updates a role in the local cache.
2008
+ * @internal
2009
+ * @param data The raw role data from the API.
2010
+ * @param idParam An optional ID parameter if the payload wraps the role object.
2011
+ * @returns The newly created or updated Role object.
2012
+ */
2013
+ _add(data, idParam) {
2014
+ const id = idParam ?? data._id ?? data.id;
2015
+ const existing = this.cache.get(id);
2016
+ if (existing) {
2017
+ existing._patch(data);
2018
+ return existing;
2019
+ }
2020
+ const role = new Role(this.client, data, this.server.id);
2021
+ this.cache.set(role.id, role);
2022
+ return role;
2023
+ }
2024
+ [util8.inspect.custom]() {
2025
+ return this.cache;
2026
+ }
2027
+ /**
2028
+ * Resolves a RoleResolvable to a Role object from the cache.
2029
+ * @param role The RoleResolvable to resolve.
2030
+ * @returns The resolved Role object, or undefined if not found.
2031
+ */
2032
+ resolve(role) {
2033
+ if (role instanceof Role) return role;
2034
+ if (typeof role === "string") {
2035
+ const id = role.replace(/[<%>]/g, "");
2036
+ return this.cache.get(id);
2037
+ }
2038
+ return void 0;
2039
+ }
2040
+ /**
2041
+ * Extracts ID from a RoleResolvable.
2042
+ * @param role The RoleResolvable to extract the ID from.
2043
+ * @returns The extracted role ID.
2044
+ * @throws TypeError if an invalid type is provided.
2045
+ */
2046
+ resolveId(role) {
2047
+ if (role instanceof Role) {
2048
+ return role.id;
2049
+ }
2050
+ if (typeof role === "string") {
2051
+ return role.replace(/[<%>]/g, "");
2052
+ }
2053
+ throw new TypeError("Invalid RoleResolvable provided. Expected a Role object or a string ID/Mention.");
2054
+ }
2055
+ /**
2056
+ * Creates a new role in this server.
2057
+ * @param options The name and optional rank of the new role
2058
+ * @returns Role The role that was created
2059
+ * @throws {Error} If the role cannot be created (e.g., lack of permissions, invalid options).
2060
+ * @throws {TypeError} If invalid options are provided.
2061
+ * @example
2062
+ * // Create a new role named "Moderator" with rank 1
2063
+ * const moderatorRole = await server.roles.create({ name: "Moderator", rank: 1 });
2064
+ * console.log(`Created role: ${moderatorRole.name} with ID: ${moderatorRole.id}`);
2065
+ */
2066
+ async create(options) {
2067
+ if (!options || typeof options !== "object") {
2068
+ throw new TypeError("RoleCreateOptions must be a valid object.");
2069
+ }
2070
+ if (typeof options.name !== "string" || options.name.trim().length === 0) {
2071
+ throw new TypeError("A valid role 'name' (string) must be provided.");
2072
+ }
2073
+ const payload = {
2074
+ name: options.name
2075
+ };
2076
+ const data = await this.client.rest.post(`/servers/${this.server.id}/roles`, payload);
2077
+ return this._add(data);
2078
+ }
2079
+ /**
2080
+ * Fetches a Role from the API or resolves it from the local cache.
2081
+ * @param role The ID, mention, or Role object to fetch.
2082
+ * @param force Whether to skip the cache check and force a direct API request. Defaults to false.
2083
+ * @returns A promise that resolves to the fetched Role object.
2084
+ * @throws {TypeError} If an invalid RoleResolvable is provided.
2085
+ * @throws {Error} If the API request fails (e.g., the role does not exist).
2086
+ * @example
2087
+ * // Fetch a role from the API
2088
+ * const role = await server.roles.fetch("01JE2MM759J5D7CHJF084R7MJ2");
2089
+ * console.log(`Fetched role: ${role.name} with ID: ${role.id}`);
2090
+ *
2091
+ * // Fetch a role by mention
2092
+ * const role = await.server.roles.fetch("<%01JE2MM759J5D7CHJF084R7MJ2>");
2093
+ * console.log(`Fetched role: ${role.name} with ID: ${role.id}`);
2094
+ *
2095
+ * // Force fetch a role, bypassing the cache
2096
+ * const role = await server.roles.fetch("01JE2MM759J5D7CHJF084R7MJ2", true);
2097
+ * console.log(`Fetched role: ${role.name} with ID: ${role.id}`);
2098
+ */
2099
+ async fetch(role, force = false) {
2100
+ if (!force) {
2101
+ const cached = this.resolve(role);
2102
+ if (cached) return cached;
2103
+ }
2104
+ const id = this.resolveId(role);
2105
+ const data = await this.client.rest.get(`/servers/${this.server.id}/roles/${id}`);
2106
+ return this._add(data);
2107
+ }
2108
+ /**
2109
+ * Edits an existing role in the server.
2110
+ * @param role The RoleResolvable to edit.
2111
+ * @param options The fields to update.
2112
+ * @returns A promise that resolves to the updated Role.
2113
+ * @throws {TypeError} If invalid options or RoleResolvable are provided.
2114
+ * @throws {Error} If the API request fails (e.g., lack of permissions).
2115
+ * @example
2116
+ * // Rename a role and give it a red color
2117
+ * await server.roles.edit("01H...", { name: "Super Admin", colour: "#FF0000" });
2118
+ *
2119
+ * // Remove the custom color from a role
2120
+ * await server.roles.edit(role, { colour: null });
2121
+ */
2122
+ async edit(role, options) {
2123
+ if (!options || typeof options !== "object") {
2124
+ throw new TypeError("RoleEditOptions must be a valid object.");
2125
+ }
2126
+ const id = this.resolveId(role);
2127
+ const payload = {};
2128
+ const remove = [];
2129
+ if (options.name !== void 0) payload.name = options.name;
2130
+ if (options.hoist !== void 0) payload.hoist = options.hoist;
2131
+ if (options.colour !== void 0) {
2132
+ if (options.colour === null) {
2133
+ remove.push("Colour");
2134
+ } else {
2135
+ payload.colour = options.colour;
2136
+ }
2137
+ }
2138
+ if (remove.length > 0) {
2139
+ payload.remove = remove;
2140
+ }
2141
+ if (Object.keys(payload).length === 0) {
2142
+ return this.fetch(id);
2143
+ }
2144
+ const data = await this.client.rest.patch(`/servers/${this.server.id}/roles/${id}`, payload);
2145
+ return this._add(data, id);
2146
+ }
2147
+ /**
2148
+ * Deletes a Role from the server.
2149
+ * @param role The RoleResolvable to delete
2150
+ * @returns A promise that resolves when the role is successfully deleted.
2151
+ * @throws {TypeError} If an invalid RoleResolvable is provided.
2152
+ * @throws {Error} If the role cannot be deleted (e.g., lack of permissions).
2153
+ * @example
2154
+ * // Delete a role by its ID
2155
+ * await server.roles.delete("01JE2MM759J5D7CHJF084R7MJ2");
2156
+ * console.log("Role deleted successfully.");
2157
+ *
2158
+ * // Delete a role using a Role object
2159
+ * const role = await server.roles.fetch("01JE2MM759J5D7CHJF084R7MJ2");
2160
+ * await server.roles.delete(role);
2161
+ * console.log("Role deleted successfully.");
2162
+ *
2163
+ * // Delete a role by mention
2164
+ * await server.roles.delete("<%01JE2MM759J5D7CHJF084R7MJ2>");
2165
+ * console.log("Role deleted successfully.");
2166
+ */
2167
+ async delete(role) {
2168
+ const id = this.resolveId(role);
2169
+ await this.client.rest.delete(`/servers/${this.server.id}/roles/${id}`);
2170
+ this.cache.delete(id);
2171
+ }
2172
+ /**
2173
+ * Updates the permissions for a role in the server.
2174
+ * @param role The RoleResolvable to update permissions for.
2175
+ * @param options The allow and deny permissions to set.
2176
+ * @returns A promise that resolves to the updated Role.
2177
+ * @throws {TypeError} If an invalid RoleResolvable or options are provided.
2178
+ * @throws {Error} If the API request fails.
2179
+ * @example
2180
+ * // Set permissions using an array of strings.
2181
+ * await server.roles.setPermissions(role, {
2182
+ * allow: ["ManageChannel", "ViewChannel", "SendMessage"]
2183
+ * });
2184
+ */
2185
+ async setPermissions(role, options) {
2186
+ if (!options || typeof options !== "object") {
2187
+ throw new TypeError("RolePermissionOptions must be a valid object.");
2188
+ }
2189
+ const id = this.resolveId(role);
2190
+ const allowBigInt = options.allow !== void 0 ? Permissions.resolve(options.allow) : 0n;
2191
+ const denyBigInt = options.deny !== void 0 ? Permissions.resolve(options.deny) : 0n;
2192
+ const payload = {
2193
+ permissions: {
2194
+ allow: Number(allowBigInt),
2195
+ deny: Number(denyBigInt)
2196
+ }
2197
+ };
2198
+ const data = await this.client.rest.put(`/servers/${this.server.id}/permissions/${id}`, payload);
2199
+ this.server._patch(data);
2200
+ return this.cache.get(id);
2201
+ }
2202
+ /**
2203
+ * Updates the hierarchical positions of roles in the server.
2204
+ * @param ranks An array of RoleResolvables representing the new order of roles.
2205
+ * @returns A promise that resolves when the ranks are successfully updated.
2206
+ * @throws {TypeError} If the ranks parameter is not an array or contains invalid resolvables.
2207
+ * @throws {Error} If the API request fails.
2208
+ * @example
2209
+ * // Reorder roles by passing an array of Role objects or IDs
2210
+ * await server.roles.setRanks(["RoleID_1", adminRoleObject, "RoleID_3"]);
2211
+ */
2212
+ async setRanks(ranks) {
2213
+ if (!Array.isArray(ranks)) {
2214
+ throw new TypeError("The 'ranks' parameter must be an array of RoleResolvables.");
2215
+ }
2216
+ const mappedIds = ranks.map((role) => this.resolveId(role));
2217
+ const payload = {
2218
+ ranks: mappedIds
2219
+ };
2220
+ const data = await this.client.rest.put(`/servers/${this.server.id}/roles`, payload);
2221
+ this.server._patch(data);
2222
+ return this.server;
2223
+ }
2224
+ };
2225
+
2226
+ // src/structures/ServerInvite.ts
2227
+ var ServerInvite = class {
2228
+ code;
2229
+ creatorId;
2230
+ channelId;
2231
+ constructor(data) {
2232
+ this.code = data._id ?? data.code;
2233
+ this.creatorId = data.creator;
2234
+ this.channelId = data.channel;
2235
+ }
2236
+ _patch(data) {
2237
+ this.creatorId = data.creator ?? this.creatorId;
2238
+ this.channelId = data.channel ?? this.channelId;
2239
+ }
2240
+ };
2241
+
2242
+ // src/managers/ServerInviteManager.ts
2243
+ var ServerInviteManager = class extends BaseManager {
2244
+ constructor(client, server, limit = Infinity) {
2245
+ super(client, limit);
2246
+ this.server = server;
2247
+ }
2248
+ extractId(data) {
2249
+ return data._id ?? data.code;
2250
+ }
2251
+ construct(data) {
2252
+ return new ServerInvite(data);
2253
+ }
2254
+ /**
2255
+ * Fetches all active invites for this server.
2256
+ */
2257
+ async fetch() {
2258
+ const data = await this.client.rest.get(`/servers/${this.server.id}/invites`);
2259
+ const rawInvites = Array.isArray(data) ? data : [];
2260
+ const fetched = new Collection();
2261
+ for (const raw of rawInvites) {
2262
+ const invite = this._add(raw);
2263
+ fetched.set(invite.code, invite);
2264
+ }
2265
+ return fetched;
2266
+ }
2267
+ };
2268
+
2269
+ // src/structures/ServerBan.ts
2270
+ var ServerBan = class {
2271
+ userId;
2272
+ reason;
2273
+ constructor(data) {
2274
+ this.userId = data._id?.user ?? data.id;
2275
+ this.reason = data.reason ?? null;
2276
+ }
2277
+ _patch(data) {
2278
+ if (data.reason !== void 0) this.reason = data.reason;
2279
+ }
2280
+ };
2281
+
2282
+ // src/managers/ServerBanManager.ts
2283
+ var ServerBanManager = class extends BaseManager {
2284
+ constructor(client, server, limit = Infinity) {
2285
+ super(client, limit);
2286
+ this.server = server;
2287
+ }
2288
+ extractId(data) {
2289
+ return data._id?.user ?? data.id;
2290
+ }
2291
+ construct(data) {
2292
+ return new ServerBan(data);
2293
+ }
2294
+ /**
2295
+ * Fetches all bans in this server.
2296
+ * Automatically caches the associated User objects globally!
2297
+ * @returns A promise that resolves to a Collection of Bans.
2298
+ */
2299
+ async fetch() {
2300
+ const data = await this.client.rest.get(`/servers/${this.server.id}/bans`);
2301
+ if (data.users && Array.isArray(data.users)) {
2302
+ for (const userData of data.users) {
2303
+ this.client.users._add(userData);
2304
+ }
2305
+ }
2306
+ const rawBans = data.bans || (Array.isArray(data) ? data : []);
2307
+ const fetched = new Collection();
2308
+ for (const rawBan of rawBans) {
2309
+ const ban = this._add(rawBan);
2310
+ fetched.set(ban.userId, ban);
2311
+ }
2312
+ return fetched;
2313
+ }
2314
+ /**
2315
+ * Unbans a user from the server.
2316
+ * @param userId The ID of the user to unban.
2317
+ */
2318
+ async remove(userId) {
2319
+ const id = userId.replace(/[<@!>]/g, "");
2320
+ await this.client.rest.delete(`/servers/${this.server.id}/bans/${id}`);
2321
+ this.cache.delete(id);
2322
+ }
2323
+ };
2324
+
2325
+ // src/structures/Server.ts
2326
+ var Server = class extends Base {
2327
+ channelIds = [];
2328
+ defaultPermissions;
2329
+ name;
2330
+ ownerId;
2331
+ analytics = false;
2332
+ banner = null;
2333
+ categories = [];
2334
+ description = null;
2335
+ discoverable = false;
2336
+ flags = 0;
2337
+ icon = null;
2338
+ nsfw = false;
2339
+ members;
2340
+ channels;
2341
+ roles;
2342
+ bans;
2343
+ invites;
2344
+ constructor(client, data) {
2345
+ super(client, data);
2346
+ this.channels = new ServerChannelManager(client, this);
2347
+ this.members = new MemberManager(client, this);
2348
+ this.roles = new RoleManager(client, this);
2349
+ this.bans = new ServerBanManager(this.client, this);
2350
+ this.invites = new ServerInviteManager(this.client, this);
2351
+ this._patch(data);
2352
+ }
2353
+ /**
2354
+ * Updates the server instance with new data without losing the object reference.
2355
+ */
2356
+ _patch(data, clear) {
2357
+ if (data.channels !== void 0) this.channelIds = data.channels;
2358
+ if (data.default_permissions !== void 0) {
2359
+ try {
2360
+ this.defaultPermissions = BigInt(data.default_permissions);
2361
+ } catch {
2362
+ this.defaultPermissions = 0n;
2363
+ }
2364
+ }
2365
+ if (data.name !== void 0) this.name = data.name;
2366
+ if (data.owner !== void 0) this.ownerId = data.owner;
2367
+ if (data.analytics !== void 0) this.analytics = data.analytics;
2368
+ if (data.categories !== void 0) this.categories = data.categories;
2369
+ if (data.description !== void 0) this.description = data.description;
2370
+ if (data.discoverable !== void 0) this.discoverable = data.discoverable;
2371
+ if (data.flags !== void 0) this.flags = data.flags;
2372
+ if (data.nsfw !== void 0) this.nsfw = data.nsfw;
2373
+ if (data.icon !== void 0) {
2374
+ this.icon = data.icon ? new Attachment(this.client, data.icon) : null;
2375
+ }
2376
+ if (data.banner !== void 0) {
2377
+ this.banner = data.banner ? new Attachment(this.client, data.banner) : null;
2378
+ }
2379
+ if (data.roles !== void 0) {
2380
+ for (const [id, roleData] of Object.entries(data.roles)) {
2381
+ this.roles._add({ id, ...roleData });
2382
+ }
2383
+ }
2384
+ if (clear && Array.isArray(clear)) {
2385
+ for (const field of clear) {
2386
+ switch (field) {
2387
+ case "Description":
2388
+ this.description = null;
2389
+ break;
2390
+ case "Icon":
2391
+ this.icon = null;
2392
+ break;
2393
+ }
2394
+ }
2395
+ }
2396
+ }
2397
+ /**
2398
+ * Edits this server.
2399
+ * @param options The fields to update.
2400
+ */
2401
+ async edit(options) {
2402
+ await this.client.servers.edit(this.id, options);
2403
+ return this;
2404
+ }
2405
+ /**
2406
+ * Leaves the server
2407
+ */
2408
+ async leave() {
2409
+ return this.client.rest.delete(`/servers/${this.id}/leave`);
2410
+ }
2411
+ /**
2412
+ * Fetches multiple members from this server.
2413
+ * @param options Filter options for the fetch request.
2414
+ * @returns A Collection of the fetched members.
2415
+ */
2416
+ async fetchMembers(options) {
2417
+ return this.members.fetchMany(options);
2418
+ }
2419
+ };
2420
+
2421
+ // src/managers/ServerManager.ts
2422
+ var util9 = __toESM(require("util"), 1);
2423
+ var ServerManager = class extends BaseManager {
2424
+ constructor(client, limit = Infinity) {
2425
+ super(client, limit);
2426
+ }
2427
+ /**
2428
+ * Tell BaseManager how to find the ID for Servers
2429
+ */
2430
+ extractId(data) {
2431
+ return data._id ?? data.id;
2432
+ }
2433
+ /**
2434
+ * Tell BaseManager how to build a Server
2435
+ */
2436
+ construct(data) {
2437
+ return new Server(this.client, data);
2438
+ }
2439
+ /**
2440
+ * Fetches a server from the API.
2441
+ * @param id The server ID.
2442
+ * @param force Whether to skip the cache and fetch from the API.
2443
+ */
2444
+ async fetch(id, force = false) {
2445
+ if (!force) {
2446
+ const cached = this.cache.get(id);
2447
+ if (cached) return cached;
2448
+ }
2449
+ const data = await this.client.rest.get(`/servers/${id}`);
2450
+ return this._add(data);
2451
+ }
2452
+ async edit(serverId, options) {
2453
+ const payload = {};
2454
+ const remove = [];
2455
+ if (options.name !== void 0) payload.name = options.name;
2456
+ if (options.description !== void 0) {
2457
+ if (options.description === null) remove.push("Description");
2458
+ else payload.description = options.description;
2459
+ }
2460
+ if (options.icon !== void 0) {
2461
+ if (options.icon === null) remove.push("Icon");
2462
+ else payload.icon = options.icon;
2463
+ }
2464
+ if (options.banner !== void 0) {
2465
+ if (options.banner === null) remove.push("Banner");
2466
+ else payload.banner = options.banner;
2467
+ }
2468
+ if (options.systemMessages) {
2469
+ payload.system_messages = {};
2470
+ const sm = options.systemMessages;
2471
+ if (sm.userJoined !== void 0) {
2472
+ if (sm.userJoined === null) remove.push("SystemMessageUserJoined");
2473
+ else payload.system_messages.user_joined = sm.userJoined;
2474
+ }
2475
+ if (sm.userLeft !== void 0) {
2476
+ if (sm.userLeft === null) remove.push("SystemMessageUserLeft");
2477
+ else payload.system_messages.user_left = sm.userLeft;
2478
+ }
2479
+ if (sm.userKicked !== void 0) {
2480
+ if (sm.userKicked === null) remove.push("SystemMessageUserKicked");
2481
+ else payload.system_messages.user_kicked = sm.userKicked;
2482
+ }
2483
+ if (sm.userBanned !== void 0) {
2484
+ if (sm.userBanned === null) remove.push("SystemMessageUserBanned");
2485
+ else payload.system_messages.user_banned = sm.userBanned;
2486
+ }
2487
+ }
2488
+ if (options.categories !== void 0) payload.categories = options.categories;
2489
+ if (options.analytics !== void 0) payload.analytics = options.analytics;
2490
+ if (options.owner !== void 0) payload.owner = options.owner;
2491
+ if (remove.length > 0) payload.remove = remove;
2492
+ const data = await this.client.rest.patch(`/servers/${serverId}`, payload);
2493
+ return this._add(data);
2494
+ }
2495
+ [util9.inspect.custom]() {
2496
+ return this.cache;
2497
+ }
2498
+ };
2499
+
2500
+ // src/managers/UserManager.ts
2501
+ var UserManager = class extends BaseManager {
2502
+ constructor(client, limit = Infinity) {
2503
+ super(client, limit);
2504
+ }
2505
+ /**
2506
+ * Tell BaseManager how to find the ID for Users
2507
+ */
2508
+ extractId(data) {
2509
+ return data._id ?? data.id;
2510
+ }
2511
+ /**
2512
+ * Tell BaseManager how to build a User
2513
+ */
2514
+ construct(data) {
2515
+ return new User(this.client, data);
2516
+ }
2517
+ /**
2518
+ * Resolves a UserResolvable to a User object from the cache.
2519
+ */
2520
+ resolve(user) {
2521
+ if (user instanceof User) return user;
2522
+ if (typeof user === "string") {
2523
+ const id = user.replace(/[<@>]/g, "");
2524
+ return this.cache.get(id);
2525
+ }
2526
+ return void 0;
2527
+ }
2528
+ /**
2529
+ * Extracts ID from a UserResolvable.
2530
+ * @param user The UserResolvable to extract the ID from.
2531
+ * @returns The extracted user ID.
2532
+ * @throws TypeError if an invalid type is provided.
2533
+ */
2534
+ resolveId(user) {
2535
+ if (user instanceof User) {
2536
+ return user.id;
2537
+ }
2538
+ if (typeof user === "string") {
2539
+ return user.replace(/[<@>]/g, "");
2540
+ }
2541
+ throw new TypeError("Invalid UserResolvable provided. Expected a User object or a string ID/Mention.");
2542
+ }
2543
+ /**
2544
+ * Fetches a User.
2545
+ * @param user The ID or mention to fetch
2546
+ * @param force Skip the cache check and force an API request
2547
+ * @returns The fetched User object
2548
+ * @throws Error if the user cannot be found or fetched
2549
+ * @throws TypeError if invalid UserResolvable is provided
2550
+ * @example
2551
+ * // Fetch a user by ID
2552
+ * const user = await client.users.fetch("01JE2MM759J5D7CHJF084R7MJ2");
2553
+ * console.log(user.username);
2554
+ *
2555
+ * // Fetch a user by mention
2556
+ * const user = await client.users.fetch("<@01JE2MM759J5D7CHJF084R7MJ2>");
2557
+ * console.log(user.username);
2558
+ *
2559
+ * // Force fetch a user, bypassing the cache
2560
+ * const user = await client.users.fetch("01JE2MM759J5D7CHJF084R7MJ2", true);
2561
+ * console.log(user.username);
2562
+ */
2563
+ async fetch(user, force = false) {
2564
+ if (!force) {
2565
+ const cached = this.resolve(user);
2566
+ if (cached) return cached;
2567
+ }
2568
+ const id = this.resolveId(user);
2569
+ const data = await this.client.rest.get(`/users/${id}`);
2570
+ return this._add(data);
2571
+ }
2572
+ /**
2573
+ * Fetch the current user (the bot itself).
2574
+ * @returns The fetched User object representing the current user.
2575
+ * @throws Error if the user cannot be fetched.
2576
+ * @example
2577
+ * // Fetch the current user (the bot itself)
2578
+ * const me = await client.users.fetchMe();
2579
+ * console.log(`Logged in as ${me.tag}`);
2580
+ */
2581
+ async fetchMe() {
2582
+ const data = await this.client.rest.get(`/users/@me`);
2583
+ return this._add(data);
2584
+ }
2585
+ /**
2586
+ * Edits the currently authenticated user (the bot itself).
2587
+ * @param options The fields to update (avatar, status, profile, etc.).
2588
+ * @returns A promise that resolves to the updated User object.
2589
+ * @throws {TypeError} If invalid options are provided.
2590
+ * @throws {Error} If the API request fails.
2591
+ * @example
2592
+ * // Update the bot's status and presence
2593
+ * await client.users.editMe({
2594
+ * status: { text: "Watching the server", presence: "Online" }
2595
+ * });
2596
+ *
2597
+ * // Clear the bot's avatar and display name
2598
+ * await client.users.editMe({ avatar: null, displayName: null });
2599
+ */
2600
+ async editMe(options) {
2601
+ if (!options || typeof options !== "object") {
2602
+ throw new TypeError("UserEditOptions must be a valid object.");
2603
+ }
2604
+ const payload = {};
2605
+ const remove = [];
2606
+ if (options.displayName !== void 0) {
2607
+ if (options.displayName === null) remove.push("DisplayName");
2608
+ else payload.display_name = options.displayName;
2609
+ }
2610
+ if (options.avatar !== void 0) {
2611
+ if (options.avatar === null) remove.push("Avatar");
2612
+ else payload.avatar = options.avatar;
2613
+ }
2614
+ if (options.profile !== void 0) {
2615
+ payload.profile = {};
2616
+ if (options.profile.content !== void 0) {
2617
+ if (options.profile.content === null) remove.push("ProfileContent");
2618
+ else payload.profile.content = options.profile.content;
2619
+ }
2620
+ if (options.profile.background !== void 0) {
2621
+ if (options.profile.background === null) remove.push("ProfileBackground");
2622
+ else payload.profile.background = options.profile.background;
2623
+ }
2624
+ if (Object.keys(payload.profile).length === 0) delete payload.profile;
2625
+ }
2626
+ if (options.status !== void 0) {
2627
+ payload.status = {};
2628
+ if (options.status.text !== void 0) {
2629
+ if (options.status.text === null) remove.push("StatusText");
2630
+ else payload.status.text = options.status.text;
2631
+ }
2632
+ if (options.status.presence !== void 0) {
2633
+ if (options.status.presence === null) remove.push("StatusPresence");
2634
+ else payload.status.presence = options.status.presence;
2635
+ }
2636
+ if (Object.keys(payload.status).length === 0) delete payload.status;
2637
+ }
2638
+ if (remove.length > 0) {
2639
+ payload.remove = remove;
2640
+ }
2641
+ if (Object.keys(payload).length === 0) {
2642
+ return this.fetch("@me");
2643
+ }
2644
+ const data = await this.client.rest.patch(`/users/@me`, payload);
2645
+ return this._add(data);
2646
+ }
2647
+ };
2648
+
2649
+ // src/managers/SweepManager.ts
2650
+ var SweeperManager = class {
2651
+ constructor(client, options) {
2652
+ this.client = client;
2653
+ this.options = options;
2654
+ }
2655
+ messageInterval = null;
2656
+ start() {
2657
+ if (this.options.messages) {
2658
+ this.client.emit("debug", "Starting Message Cache Sweeper...");
2659
+ this.messageInterval = setInterval(() => {
2660
+ this.sweepMessages();
2661
+ }, this.options.messages.interval);
2662
+ }
2663
+ }
2664
+ sweepMessages() {
2665
+ if (!this.options.messages) return;
2666
+ const now = Date.now();
2667
+ const lifetime = this.options.messages.lifetime;
2668
+ let sweptCount = 0;
2669
+ for (const channel of this.client.channels.cache.values()) {
2670
+ if (!("messages" in channel)) continue;
2671
+ const textChannel = channel;
2672
+ for (const [id, message] of textChannel.messages.cache.entries()) {
2673
+ if (now - message.cachedAt > lifetime) {
2674
+ textChannel.messages.cache.delete(id);
2675
+ sweptCount++;
2676
+ }
2677
+ }
2678
+ }
2679
+ if (sweptCount > 0) {
2680
+ this.client.emit("debug", `\u{1F9F9} Sweeper cleared ${sweptCount} old messages from cache.`);
2681
+ }
2682
+ }
2683
+ stop() {
2684
+ if (this.messageInterval) clearInterval(this.messageInterval);
2685
+ this.client.emit("debug", "Sweepers stopped.");
2686
+ }
2687
+ };
2688
+
2689
+ // src/client/Client.ts
2690
+ var Client = class extends import_events.EventEmitter {
2691
+ constructor(options = {}) {
2692
+ super({ captureRejections: true });
2693
+ this.options = options;
2694
+ this.rest = new RESTManager(this);
2695
+ this.gateway = new GatewayManager(this);
2696
+ this.channels = new ChannelManager(this, options.cacheLimits?.channels);
2697
+ this.servers = new ServerManager(this, options.cacheLimits?.servers);
2698
+ this.users = new UserManager(this, options.cacheLimits?.users);
2699
+ this.sweepers = new SweeperManager(this, options.sweepers ?? {});
2700
+ }
2701
+ rest;
2702
+ gateway;
2703
+ channels;
2704
+ servers;
2705
+ users;
2706
+ sweepers;
2707
+ user = null;
2708
+ /**
2709
+ * Connects the bot to the Stoat Gateway
2710
+ */
2711
+ async login(token) {
2712
+ if (!token) throw new Error("A valid token must be provided.");
2713
+ this.sweepers.start();
2714
+ this.rest.setToken(token);
2715
+ return this.gateway.connect(token);
2716
+ }
2717
+ [/* @__PURE__ */ Symbol.for("nodejs.rejection")](error) {
2718
+ this.emit("error", error);
2719
+ }
2720
+ on(event, listener) {
2721
+ return super.on(event, listener);
2722
+ }
2723
+ once(event, listener) {
2724
+ return super.once(event, listener);
2725
+ }
2726
+ emit(event, ...args) {
2727
+ return super.emit(event, ...args);
2728
+ }
2729
+ };
2730
+
2731
+ // src/builders/EmbedBuilder.ts
2732
+ var EmbedBuilder = class {
2733
+ data;
2734
+ constructor(data = {}) {
2735
+ this.data = { type: "Text", ...data };
2736
+ }
2737
+ setTitle(title) {
2738
+ this.data.title = title;
2739
+ return this;
2740
+ }
2741
+ setDescription(description) {
2742
+ this.data.description = description;
2743
+ return this;
2744
+ }
2745
+ setUrl(url) {
2746
+ this.data.url = url;
2747
+ return this;
2748
+ }
2749
+ setIconUrl(iconUrl) {
2750
+ this.data.icon_url = iconUrl;
2751
+ return this;
2752
+ }
2753
+ setColor(color) {
2754
+ this.data.colour = color;
2755
+ return this;
2756
+ }
2757
+ setMedia(fileId) {
2758
+ this.data.media = fileId;
2759
+ return this;
2760
+ }
2761
+ /**
2762
+ * Serializes the builder into the raw JSON required by the API
2763
+ */
2764
+ toJSON() {
2765
+ return { ...this.data };
2766
+ }
2767
+ };
2768
+ // Annotate the CommonJS export names for ESM import in node:
2769
+ 0 && (module.exports = {
2770
+ Attachment,
2771
+ Base,
2772
+ BaseChannel,
2773
+ ChannelManager,
2774
+ ChannelType,
2775
+ Client,
2776
+ ClientUser,
2777
+ Collection,
2778
+ DMChannel,
2779
+ EmbedBuilder,
2780
+ GatewayManager,
2781
+ Member,
2782
+ MemberManager,
2783
+ Message,
2784
+ MessageManager,
2785
+ PermissionFlags,
2786
+ Permissions,
2787
+ RESTManager,
2788
+ Role,
2789
+ RoleManager,
2790
+ Server,
2791
+ ServerChannelManager,
2792
+ ServerManager,
2793
+ SweeperManager,
2794
+ TextChannel,
2795
+ UnknownChannel,
2796
+ User,
2797
+ UserManager,
2798
+ UserPresence,
2799
+ UserRelationship
2800
+ });