@stoatx/client 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -30,11 +30,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ API: () => API,
33
34
  Attachment: () => Attachment,
35
+ AttachmentBuilder: () => AttachmentBuilder,
34
36
  Base: () => Base,
35
37
  BaseChannel: () => BaseChannel,
38
+ BitField: () => BitField,
36
39
  ChannelManager: () => ChannelManager,
37
- ChannelType: () => ChannelType,
38
40
  Client: () => Client,
39
41
  ClientUser: () => ClientUser,
40
42
  Collection: () => Collection,
@@ -64,9 +66,7 @@ __export(index_exports, {
64
66
  TextChannel: () => TextChannel,
65
67
  UnknownChannel: () => UnknownChannel,
66
68
  User: () => User,
67
- UserManager: () => UserManager,
68
- UserPresence: () => UserPresence,
69
- UserRelationship: () => UserRelationship
69
+ UserManager: () => UserManager
70
70
  });
71
71
  module.exports = __toCommonJS(index_exports);
72
72
 
@@ -129,7 +129,7 @@ var Attachment = class extends Base {
129
129
  serverId;
130
130
  objectId;
131
131
  constructor(client, data) {
132
- super(client, { ...data, id: data._id });
132
+ super(client, { ...data, _id: data._id });
133
133
  this.id = data._id;
134
134
  this.tag = data.tag;
135
135
  this.filename = data.filename;
@@ -470,7 +470,7 @@ var Message = class extends Base {
470
470
  flags = 0;
471
471
  interactions = null;
472
472
  masquerade = null;
473
- mentions = [];
473
+ mentions = null;
474
474
  pinned = false;
475
475
  reactions = {};
476
476
  replies = [];
@@ -645,7 +645,7 @@ var Message = class extends Base {
645
645
  }
646
646
  _patch(data) {
647
647
  if (data.content !== void 0) this.content = data.content;
648
- if (data.edited !== void 0) this.editedAt = new Date(data.edited);
648
+ if (data.edited !== void 0) this.editedAt = new Date(data.edited ?? 0);
649
649
  if (data.pinned !== void 0) this.pinned = data.pinned;
650
650
  if (data.embeds !== void 0) this.embeds = data.embeds;
651
651
  if (data.flags !== void 0) this.flags = data.flags;
@@ -678,24 +678,6 @@ var Message = class extends Base {
678
678
  };
679
679
 
680
680
  // src/structures/User.ts
681
- var UserRelationship = /* @__PURE__ */ ((UserRelationship2) => {
682
- UserRelationship2["None"] = "None";
683
- UserRelationship2["User"] = "User";
684
- UserRelationship2["Friend"] = "Friend";
685
- UserRelationship2["Outgoing"] = "Outgoing";
686
- UserRelationship2["Incoming"] = "Incoming";
687
- UserRelationship2["Blocked"] = "Blocked";
688
- UserRelationship2["BlockedOther"] = "BlockedOther";
689
- return UserRelationship2;
690
- })(UserRelationship || {});
691
- var UserPresence = /* @__PURE__ */ ((UserPresence2) => {
692
- UserPresence2["Online"] = "Online";
693
- UserPresence2["Idle"] = "Idle";
694
- UserPresence2["Focus"] = "Focus";
695
- UserPresence2["Busy"] = "Busy";
696
- UserPresence2["Invisible"] = "Invisible";
697
- return UserPresence2;
698
- })(UserPresence || {});
699
681
  var User = class extends Base {
700
682
  discriminator;
701
683
  online;
@@ -729,7 +711,7 @@ var User = class extends Base {
729
711
  this.bot = data.bot ? { owner: data.bot.owner } : false;
730
712
  }
731
713
  if (data.avatar !== void 0) {
732
- this.avatar = new Attachment(this.client, data.avatar);
714
+ this.avatar = data.avatar ? new Attachment(this.client, data.avatar) : null;
733
715
  }
734
716
  if (clear && Array.isArray(clear)) {
735
717
  for (const field of clear) {
@@ -809,6 +791,7 @@ var GatewayManager = class {
809
791
  handleMessage(rawData) {
810
792
  const payload = JSON.parse(rawData.toString());
811
793
  const eventType = payload.type;
794
+ this.client.emit("raw", payload);
812
795
  switch (eventType) {
813
796
  case "Error":
814
797
  this.client.emit("error", new Error(`Gateway Error: ${payload.error || JSON.stringify(payload)}`));
@@ -886,7 +869,7 @@ var GatewayManager = class {
886
869
  const message = channel?.messages.cache.get(payload.id);
887
870
  if (message && payload.append.embeds) {
888
871
  const oldMessage = message._clone();
889
- message.embeds.push(...payload.append.embeds);
872
+ message.embeds = [...message.embeds || [], ...payload.append.embeds];
890
873
  this.client.emit("messageUpdate", oldMessage, message);
891
874
  }
892
875
  break;
@@ -1026,13 +1009,28 @@ var GatewayManager = class {
1026
1009
  }
1027
1010
  case "ServerMemberLeave": {
1028
1011
  const server = this.client.servers.cache.get(payload.id);
1012
+ let member = null;
1029
1013
  if (server) {
1030
- const member = server.members.cache.get(payload.user);
1014
+ member = server.members.cache.get(payload.user);
1031
1015
  if (member) {
1032
1016
  server.members.cache.delete(payload.user);
1033
- this.client.emit("serverMemberLeave", member);
1034
1017
  }
1035
1018
  }
1019
+ const emitData = member || { serverId: payload.id, userId: payload.user };
1020
+ if (payload.reason === "Ban") {
1021
+ if (server) {
1022
+ const dummyBanPayload = {
1023
+ id: payload.user,
1024
+ reason: null
1025
+ };
1026
+ server.bans._add(dummyBanPayload);
1027
+ }
1028
+ this.client.emit("serverBanAdd", emitData);
1029
+ } else if (payload.reason === "Kick") {
1030
+ this.client.emit("serverMemberKick", emitData);
1031
+ } else {
1032
+ this.client.emit("serverMemberLeave", emitData);
1033
+ }
1036
1034
  break;
1037
1035
  }
1038
1036
  case "EmojiCreate": {
@@ -1066,7 +1064,8 @@ var GatewayManager = class {
1066
1064
  break;
1067
1065
  }
1068
1066
  default:
1069
- this.client.emit("raw", payload);
1067
+ this.client.emit("debug", `Unhandled Gateway Event Type: ${eventType}`);
1068
+ break;
1070
1069
  }
1071
1070
  }
1072
1071
  startPingLoop() {
@@ -1112,6 +1111,96 @@ var GatewayManager = class {
1112
1111
 
1113
1112
  // src/rest/RESTManager.ts
1114
1113
  var import_undici = require("undici");
1114
+
1115
+ // src/utils/schema.ts
1116
+ var queryParams = {
1117
+ "/": { get: [] },
1118
+ "/users/@me": { get: [] },
1119
+ "/users/{target}": { get: [], patch: [] },
1120
+ "/users/{target}/flags": { get: [] },
1121
+ "/users/@me/username": { patch: [] },
1122
+ "/users/{target}/default_avatar": { get: [] },
1123
+ "/users/{target}/profile": { get: [] },
1124
+ "/users/dms": { get: [] },
1125
+ "/users/{target}/dm": { get: [] },
1126
+ "/users/{target}/mutual": { get: [] },
1127
+ "/users/{target}/friend": { put: [], delete: [] },
1128
+ "/users/{target}/block": { put: [], delete: [] },
1129
+ "/users/friend": { post: [] },
1130
+ "/bots/create": { post: [] },
1131
+ "/bots/{target}/invite": { get: [], post: [] },
1132
+ "/bots/{bot_id}": { get: [], delete: [], patch: [] },
1133
+ "/bots/@me": { get: [] },
1134
+ "/channels/{target}/ack/{message}": { put: [] },
1135
+ "/channels/{target}": { get: [], delete: ["leave_silently"], patch: [] },
1136
+ "/channels/{target}/members": { get: [] },
1137
+ "/channels/{target}/invites": { post: [] },
1138
+ "/channels/{target}/messages": { get: ["limit", "before", "after", "sort", "nearby", "include_users"], post: [] },
1139
+ "/channels/{target}/search": { post: [] },
1140
+ "/channels/{target}/messages/{msg}/pin": { post: [], delete: [] },
1141
+ "/channels/{target}/messages/{msg}": { get: [], delete: [], patch: [] },
1142
+ "/channels/{target}/messages/bulk": { delete: [] },
1143
+ "/channels/create": { post: [] },
1144
+ "/channels/{group_id}/recipients/{member_id}": { put: [], delete: [] },
1145
+ "/channels/{target}/join_call": { post: [] },
1146
+ "/channels/{target}/end_ring/{target_user}": { put: [] },
1147
+ "/channels/{target}/permissions/{role_id}": { put: [] },
1148
+ "/channels/{target}/permissions/default": { put: [] },
1149
+ "/channels/{target}/messages/{msg}/reactions/{emoji}": { put: [], delete: ["user_id", "remove_all"] },
1150
+ "/channels/{target}/messages/{msg}/reactions": { delete: [] },
1151
+ "/channels/{channel_id}/webhooks": { get: [], post: [] },
1152
+ "/servers/create": { post: [] },
1153
+ "/servers/{target}": { get: ["include_channels"], delete: ["leave_silently"], patch: [] },
1154
+ "/servers/{target}/ack": { put: [] },
1155
+ "/servers/{server}/channels": { post: [] },
1156
+ "/servers/{target}/members": { get: ["exclude_offline"] },
1157
+ "/servers/{server_id}/members/{member_id}": { get: ["roles"], delete: [], patch: [] },
1158
+ "/servers/{target}/members_experimental_query": { get: ["query", "experimental_api"] },
1159
+ "/servers/{server}/bans/{target}": { put: [], delete: [] },
1160
+ "/servers/{target}/bans": { get: [] },
1161
+ "/servers/{target}/invites": { get: [] },
1162
+ "/servers/{target}/roles": { post: [] },
1163
+ "/servers/{target}/roles/{role_id}": { get: [], delete: [], patch: [] },
1164
+ "/servers/{target}/permissions/{role_id}": { put: [] },
1165
+ "/servers/{target}/permissions/default": { put: [] },
1166
+ "/servers/{target}/emojis": { get: [] },
1167
+ "/servers/{target}/roles/ranks": { patch: [] },
1168
+ "/invites/{target}": { get: [], post: [], delete: [] },
1169
+ "/custom/emoji/{emoji_id}": { get: [], put: [], delete: [], patch: [] },
1170
+ "/safety/report": { post: [] },
1171
+ "/auth/account/create": { post: [] },
1172
+ "/auth/account/reverify": { post: [] },
1173
+ "/auth/account/delete": { put: [], post: [] },
1174
+ "/auth/account/": { get: [] },
1175
+ "/auth/account/disable": { post: [] },
1176
+ "/auth/account/change/password": { patch: [] },
1177
+ "/auth/account/change/email": { patch: [] },
1178
+ "/auth/account/verify/{code}": { post: [] },
1179
+ "/auth/account/reset_password": { post: [], patch: [] },
1180
+ "/auth/session/login": { post: [] },
1181
+ "/auth/session/logout": { post: [] },
1182
+ "/auth/session/all": { get: [], delete: ["revoke_self"] },
1183
+ "/auth/session/{id}": { delete: [], patch: [] },
1184
+ "/auth/mfa/ticket": { put: [] },
1185
+ "/auth/mfa/": { get: [] },
1186
+ "/auth/mfa/recovery": { post: [], patch: [] },
1187
+ "/auth/mfa/methods": { get: [] },
1188
+ "/auth/mfa/totp": { put: [], post: [], delete: [] },
1189
+ "/onboard/hello": { get: [] },
1190
+ "/onboard/complete": { post: [] },
1191
+ "/policy/acknowledge": { post: [] },
1192
+ "/push/subscribe": { post: [] },
1193
+ "/push/unsubscribe": { post: [] },
1194
+ "/sync/settings/fetch": { post: [] },
1195
+ "/sync/settings/set": { post: ["timestamp"] },
1196
+ "/sync/unreads": { get: [] },
1197
+ "/webhooks/{webhook_id}/{token}/{message_id}": { delete: [], patch: [] },
1198
+ "/webhooks/{webhook_id}/{token}": { get: [], post: [], delete: [], patch: [] },
1199
+ "/webhooks/{webhook_id}": { get: [], delete: [], patch: [] },
1200
+ "/webhooks/{webhook_id}/{token}/github": { post: [] }
1201
+ };
1202
+
1203
+ // src/rest/RESTManager.ts
1115
1204
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1116
1205
  var AsyncBucket = class {
1117
1206
  remaining = 1;
@@ -1158,9 +1247,25 @@ var StoatAPIError = class _StoatAPIError extends Error {
1158
1247
  Object.setPrototypeOf(this, _StoatAPIError.prototype);
1159
1248
  }
1160
1249
  };
1250
+ var ALL_QUERY_KEYS = /* @__PURE__ */ new Set();
1251
+ for (const routes of Object.values(queryParams)) {
1252
+ for (const keys of Object.values(routes)) {
1253
+ for (const key of keys) {
1254
+ ALL_QUERY_KEYS.add(key);
1255
+ }
1256
+ }
1257
+ }
1161
1258
  var RESTManager = class {
1162
1259
  constructor(client) {
1163
1260
  this.client = client;
1261
+ setInterval(() => {
1262
+ const now = Date.now();
1263
+ for (const [key, bucket] of this.buckets.entries()) {
1264
+ if (now > bucket.resetAt && bucket.remaining > 0) {
1265
+ this.buckets.delete(key);
1266
+ }
1267
+ }
1268
+ }, 3e5).unref();
1164
1269
  }
1165
1270
  baseURL = "https://stoat.chat/api";
1166
1271
  token = null;
@@ -1174,17 +1279,35 @@ var RESTManager = class {
1174
1279
  getRouteKey(method, endpoint) {
1175
1280
  return `${method}:${endpoint}`;
1176
1281
  }
1177
- makeRequest(method, endpoint, body) {
1178
- const routeKey = this.getRouteKey(method, endpoint);
1179
- let bucket = this.buckets.get(routeKey);
1180
- if (!bucket) {
1181
- bucket = new AsyncBucket();
1182
- this.buckets.set(routeKey, bucket);
1282
+ makeRequest(method, endpoint, params) {
1283
+ let finalEndpoint = endpoint;
1284
+ let finalBody = void 0;
1285
+ if (params && typeof params === "object") {
1286
+ const query = new URLSearchParams();
1287
+ finalBody = {};
1288
+ for (const [key, value] of Object.entries(params)) {
1289
+ if (value !== void 0) {
1290
+ if (ALL_QUERY_KEYS.has(key)) {
1291
+ query.append(key, String(value));
1292
+ } else {
1293
+ finalBody[key] = value;
1294
+ }
1295
+ }
1296
+ }
1297
+ const qs = query.toString();
1298
+ if (qs) finalEndpoint += `?${qs}`;
1299
+ if (Object.keys(finalBody).length === 0) finalBody = void 0;
1183
1300
  }
1301
+ const routeKey = this.getRouteKey(method, finalEndpoint);
1184
1302
  return new Promise((resolve, reject) => {
1303
+ let bucket = this.buckets.get(routeKey);
1304
+ if (!bucket) {
1305
+ bucket = new AsyncBucket();
1306
+ this.buckets.set(routeKey, bucket);
1307
+ }
1185
1308
  bucket.queue = bucket.queue.then(async () => {
1186
1309
  try {
1187
- const result = await this.execute(method, endpoint, body, bucket);
1310
+ const result = await this.execute(method, finalEndpoint, finalBody, bucket);
1188
1311
  resolve(result);
1189
1312
  } catch (error) {
1190
1313
  reject(error);
@@ -1240,9 +1363,9 @@ var RESTManager = class {
1240
1363
  /**
1241
1364
  * Uploads a file to Stoat's CDN and returns the File ID
1242
1365
  */
1243
- async uploadFile(filename, fileBuffer) {
1366
+ async uploadFile(tag, fileBuffer, filename) {
1244
1367
  if (!this.token) throw new Error("REST_NOT_READY: No token available.");
1245
- const url = "https://cdn.stoatusercontent.com/attachments";
1368
+ const url = `https://cdn.stoatusercontent.com/${tag}`;
1246
1369
  const formData = new FormData();
1247
1370
  formData.append("file", new Blob([fileBuffer]), filename);
1248
1371
  const response = await fetch(url, {
@@ -1265,20 +1388,20 @@ var RESTManager = class {
1265
1388
  const data = await response.json();
1266
1389
  return data.id;
1267
1390
  }
1268
- get(endpoint) {
1269
- return this.makeRequest("GET", endpoint);
1391
+ get(endpoint, params) {
1392
+ return this.makeRequest("get", endpoint, params);
1270
1393
  }
1271
- post(endpoint, body) {
1272
- return this.makeRequest("POST", endpoint, body);
1394
+ post(endpoint, params) {
1395
+ return this.makeRequest("post", endpoint, params);
1273
1396
  }
1274
- patch(endpoint, body) {
1275
- return this.makeRequest("PATCH", endpoint, body);
1397
+ patch(endpoint, params) {
1398
+ return this.makeRequest("patch", endpoint, params);
1276
1399
  }
1277
- delete(endpoint, body) {
1278
- return this.makeRequest("DELETE", endpoint, body);
1400
+ delete(endpoint, params) {
1401
+ return this.makeRequest("delete", endpoint, params);
1279
1402
  }
1280
- async put(endpoint, body) {
1281
- return this.makeRequest("PUT", endpoint, body);
1403
+ put(endpoint, params) {
1404
+ return this.makeRequest("put", endpoint, params);
1282
1405
  }
1283
1406
  };
1284
1407
 
@@ -1310,6 +1433,42 @@ var BaseManager = class {
1310
1433
  }
1311
1434
  };
1312
1435
 
1436
+ // src/builders/AttachmentBuilder.ts
1437
+ var AttachmentBuilder = class {
1438
+ // Filename for CDN to use, optional but recommended
1439
+ filename = void 0;
1440
+ file;
1441
+ /**
1442
+ * Creates a new AttachmentBuilder with the given file and optional filename.
1443
+ * @param file The file data as a Buffer or Blob.
1444
+ * @param filename An optional filename to use for the uploaded file. If not provided, the CDN will assign a default name.
1445
+ * Providing a filename can help with organization and debugging, but is not strictly required.
1446
+ * @example
1447
+ * // Create an attachment from a Buffer with a custom filename
1448
+ * const buffer = Buffer.from("Hello, world!");
1449
+ * const attachment = new AttachmentBuilder(buffer, "greeting.txt");
1450
+ */
1451
+ constructor(file, filename) {
1452
+ this.filename = filename;
1453
+ this.file = file;
1454
+ }
1455
+ /**
1456
+ * Uploads this attachment to the Stoat CDN and returns the resulting file ID.
1457
+ * @internal — use `resolveAttachment()` instead of calling this directly.
1458
+ */
1459
+ async upload(rest, tag) {
1460
+ return rest.uploadFile(tag, this.file, this.filename);
1461
+ }
1462
+ };
1463
+
1464
+ // src/utils/resolveAttachment.ts
1465
+ async function resolveAttachment(rest, value, tag) {
1466
+ if (value instanceof AttachmentBuilder) {
1467
+ return value.upload(rest, tag);
1468
+ }
1469
+ return value;
1470
+ }
1471
+
1313
1472
  // src/managers/MessageManager.ts
1314
1473
  var MessageManager = class extends BaseManager {
1315
1474
  constructor(client, channel, limit = Infinity) {
@@ -1320,7 +1479,7 @@ var MessageManager = class extends BaseManager {
1320
1479
  * Tell BaseManager how to find the ID for Messages
1321
1480
  */
1322
1481
  extractId(data) {
1323
- return data._id ?? data.id;
1482
+ return data._id;
1324
1483
  }
1325
1484
  /**
1326
1485
  * Tell BaseManager how to build a Message
@@ -1345,20 +1504,31 @@ var MessageManager = class extends BaseManager {
1345
1504
  * const history = await channel.messages.fetchMany({ limit: 20, before: "01H..." });
1346
1505
  */
1347
1506
  async fetchMany(options = {}) {
1348
- const params = new URLSearchParams();
1349
- if (options.limit !== void 0) params.append("limit", options.limit.toString());
1350
- if (options.before !== void 0) params.append("before", options.before);
1351
- if (options.after !== void 0) params.append("after", options.after);
1352
- if (options.sort !== void 0) params.append("sort", options.sort);
1353
- if (options.nearby !== void 0) params.append("nearby", options.nearby);
1354
- if (options.includeUsers !== void 0) params.append("include_users", options.includeUsers.toString());
1355
- const queryString = params.toString();
1356
- const endpoint = `/channels/${this.channel.id}/messages${queryString ? `?${queryString}` : ""}`;
1357
- const data = await this.client.rest.get(endpoint);
1358
- const rawMessages = Array.isArray(data) ? data : data.messages || [];
1359
- if (!Array.isArray(data) && data.users) {
1360
- for (const userData of data.users) {
1361
- this.client.users._add(userData);
1507
+ const endpoint = `/channels/${this.channel.id}/messages`;
1508
+ const query = {};
1509
+ if (options.limit !== void 0) query.limit = options.limit;
1510
+ if (options.before !== void 0) query.before = options.before;
1511
+ if (options.after !== void 0) query.after = options.after;
1512
+ if (options.sort !== void 0) query.sort = options.sort;
1513
+ if (options.nearby !== void 0) query.nearby = options.nearby;
1514
+ if (options.includeUsers !== void 0) query.include_users = options.includeUsers;
1515
+ const data = await this.client.rest.get(endpoint, query);
1516
+ let rawMessages;
1517
+ if (Array.isArray(data)) {
1518
+ rawMessages = data;
1519
+ } else {
1520
+ rawMessages = data.messages;
1521
+ if (data.users) {
1522
+ for (const userData of data.users) {
1523
+ this.client.users._add(userData);
1524
+ }
1525
+ }
1526
+ if (data.members && this.channel.isText()) {
1527
+ const serverId = this.channel.serverId;
1528
+ const server = await this.client.servers.fetch(serverId);
1529
+ for (const memberData of data.members) {
1530
+ server.members._add(memberData);
1531
+ }
1362
1532
  }
1363
1533
  }
1364
1534
  const fetched = new Collection();
@@ -1379,11 +1549,19 @@ var MessageManager = class extends BaseManager {
1379
1549
  * @returns A promise that resolves to the sent Message.
1380
1550
  */
1381
1551
  async send(contentOrOptions) {
1382
- const payload = typeof contentOrOptions === "string" ? { content: contentOrOptions } : { ...contentOrOptions };
1383
- if (payload.embeds) {
1384
- payload.embeds = payload.embeds.map(
1385
- (embed) => typeof embed.toJSON === "function" ? embed.toJSON() : embed
1552
+ const opts = typeof contentOrOptions === "string" ? { content: contentOrOptions } : contentOrOptions;
1553
+ const payload = {};
1554
+ if (opts.embeds && opts.embeds.length) {
1555
+ payload.embeds = opts.embeds.map((embed) => typeof embed.toJSON === "function" ? embed.toJSON() : embed);
1556
+ }
1557
+ if (opts.attachments && opts.attachments.length > 0) {
1558
+ const resolved = await Promise.all(
1559
+ opts.attachments.map((attachment) => resolveAttachment(this.client.rest, attachment, "attachments"))
1386
1560
  );
1561
+ const validAttachments = resolved.filter((id) => id !== void 0);
1562
+ if (validAttachments.length > 0) {
1563
+ payload.attachments = validAttachments;
1564
+ }
1387
1565
  }
1388
1566
  const data = await this.client.rest.post(`/channels/${this.channel.id}/messages`, payload);
1389
1567
  return new Message(this.client, data);
@@ -1396,19 +1574,20 @@ var MessageManager = class extends BaseManager {
1396
1574
  */
1397
1575
  async edit(message, contentOrOptions) {
1398
1576
  const id = this.resolveId(message);
1399
- const payload = typeof contentOrOptions === "string" ? { content: contentOrOptions } : { ...contentOrOptions };
1400
- if (payload.embeds) {
1401
- payload.embeds = payload.embeds.map(
1402
- (embed) => typeof embed.toJSON === "function" ? embed.toJSON() : embed
1403
- );
1577
+ const opts = typeof contentOrOptions === "string" ? { content: contentOrOptions } : contentOrOptions;
1578
+ const payload = {};
1579
+ if (opts.content !== void 0) {
1580
+ payload.content = opts.content;
1404
1581
  }
1405
- const data = await this.client.rest.patch(`/channels/${this.channel.id}/messages/${id}`, payload);
1406
- const existing = this.cache.get(id);
1407
- if (existing) {
1408
- existing._patch(data);
1409
- return existing;
1582
+ if (opts.embeds !== void 0) {
1583
+ if (opts.embeds === null) {
1584
+ payload.embeds = [];
1585
+ } else {
1586
+ payload.embeds = opts.embeds.map((embed) => "toJSON" in embed ? embed.toJSON() : embed);
1587
+ }
1410
1588
  }
1411
- return new Message(this.client, data);
1589
+ const data = await this.client.rest.patch(`/channels/${this.channel.id}/messages/${id}`, payload);
1590
+ return this._add(data);
1412
1591
  }
1413
1592
  /**
1414
1593
  * Deletes a message from the channel.
@@ -1425,7 +1604,7 @@ var MessageManager = class extends BaseManager {
1425
1604
  */
1426
1605
  async pin(message) {
1427
1606
  const id = this.resolveId(message);
1428
- await this.client.rest.post(`/channels/${this.channel.id}/messages/${id}/pin`, {});
1607
+ await this.client.rest.post(`/channels/${this.channel.id}/messages/${id}/pin`);
1429
1608
  const existing = this.cache.get(id);
1430
1609
  if (existing) existing.pinned = true;
1431
1610
  }
@@ -1471,12 +1650,14 @@ var MessageManager = class extends BaseManager {
1471
1650
  async removeReaction(message, reaction, userId, removeAll) {
1472
1651
  const id = this.resolveId(message);
1473
1652
  const targetUser = userId ? this.client.users.resolveId(userId) : void 0;
1474
- const params = new URLSearchParams();
1475
- if (targetUser) params.append("user_id", targetUser);
1476
- if (removeAll) params.append("remove_all", "true");
1477
- const queryString = params.toString();
1478
- const endpoint = `/channels/${this.channel.id}/messages/${id}/reactions/${encodeURIComponent(reaction)}${queryString ? `?${queryString}` : ""}`;
1479
- await this.client.rest.delete(endpoint);
1653
+ const endpoint = `/channels/${this.channel.id}/messages/${id}/reactions/${reaction}`;
1654
+ const query = {};
1655
+ if (targetUser) {
1656
+ query.user_id = targetUser;
1657
+ } else if (removeAll) {
1658
+ query.remove_all = true;
1659
+ }
1660
+ await this.client.rest.delete(endpoint, query);
1480
1661
  }
1481
1662
  /**
1482
1663
  * Remove all reactions from a message
@@ -1539,12 +1720,6 @@ var MessageCollector = class extends Collector {
1539
1720
  };
1540
1721
 
1541
1722
  // src/structures/BaseChannel.ts
1542
- var ChannelType = /* @__PURE__ */ ((ChannelType2) => {
1543
- ChannelType2["TEXT"] = "TextChannel";
1544
- ChannelType2["DM"] = "DirectMessage";
1545
- ChannelType2["GROUP"] = "Group";
1546
- return ChannelType2;
1547
- })(ChannelType || {});
1548
1723
  var BaseChannel = class extends Base {
1549
1724
  type;
1550
1725
  messages;
@@ -1668,13 +1843,13 @@ var BaseChannel = class extends Base {
1668
1843
  });
1669
1844
  }
1670
1845
  isText() {
1671
- return this.type === "TextChannel" /* TEXT */;
1846
+ return this.type === "TextChannel";
1672
1847
  }
1673
1848
  isDM() {
1674
- return this.type === "DirectMessage" /* DM */;
1849
+ return this.type === "DirectMessage";
1675
1850
  }
1676
1851
  isGroup() {
1677
- return this.type === "Group" /* GROUP */;
1852
+ return this.type === "Group";
1678
1853
  }
1679
1854
  };
1680
1855
 
@@ -1694,7 +1869,9 @@ var TextChannel = class extends BaseChannel {
1694
1869
  this.serverId = data.server;
1695
1870
  this.defaultPermissions = data.default_permissions;
1696
1871
  this.description = data.description;
1697
- this.icon = data.icon;
1872
+ if (data.icon !== void 0) {
1873
+ this.icon = data.icon ? new Attachment(this.client, data.icon) : null;
1874
+ }
1698
1875
  this.lastMessageId = data.last_message_id;
1699
1876
  this.nsfw = data.nsfw ?? false;
1700
1877
  this.slowmode = data.slowmode ?? 0;
@@ -1764,6 +1941,9 @@ var TextChannel = class extends BaseChannel {
1764
1941
  async setCategory(category) {
1765
1942
  const serverId = this.serverId;
1766
1943
  const server = await this.client.servers.fetch(serverId);
1944
+ if (!server.categories || server.categories.length === 0) {
1945
+ throw new Error("This server has no categories to move the channel into.");
1946
+ }
1767
1947
  const categories = server.categories.map((c) => ({
1768
1948
  id: c.id,
1769
1949
  title: c.title,
@@ -1794,6 +1974,9 @@ var TextChannel = class extends BaseChannel {
1794
1974
  async setPosition(position) {
1795
1975
  const serverId = this.serverId;
1796
1976
  const server = await this.client.servers.fetch(serverId);
1977
+ if (!server.categories || server.categories.length === 0) {
1978
+ throw new Error("This server has no categories to move the channel into.");
1979
+ }
1797
1980
  const categories = server.categories.map((c) => ({
1798
1981
  id: c.id,
1799
1982
  title: c.title,
@@ -1981,18 +2164,245 @@ var GroupChannel = class extends BaseChannel {
1981
2164
  // src/utils/ChannelFactory.ts
1982
2165
  function createChannel(client, data) {
1983
2166
  switch (data.channel_type) {
1984
- case "TextChannel" /* TEXT */:
2167
+ case "TextChannel":
1985
2168
  return new TextChannel(client, data);
1986
- case "DirectMessage" /* DM */:
2169
+ case "DirectMessage":
1987
2170
  return new DMChannel(client, data);
1988
- case "Group" /* GROUP */:
2171
+ case "Group":
1989
2172
  return new GroupChannel(client, data);
1990
2173
  default:
1991
- client.emit("debug", `Received unknown channel type: ${data.type}`);
2174
+ client.emit("debug", `Received unknown channel type: ${data.channel_type}`);
1992
2175
  return new UnknownChannel(client, data);
1993
2176
  }
1994
2177
  }
1995
2178
 
2179
+ // src/utils/BitField.ts
2180
+ var BitField = class _BitField {
2181
+ static Flags = {};
2182
+ static DefaultBit = 0;
2183
+ bitfield;
2184
+ constructor(bits) {
2185
+ this.bitfield = this.constructor.resolve(
2186
+ bits ?? this.constructor.DefaultBit
2187
+ );
2188
+ }
2189
+ /**
2190
+ * Checks whether this bitfield has any of the given bits set.
2191
+ *
2192
+ * @param bit The bit(s) to test against.
2193
+ * @returns `true` if at least one of the provided bits is set.
2194
+ *
2195
+ * @example
2196
+ * perms.any(['SendMessage', 'ManageChannel']); // true if either is set
2197
+ */
2198
+ any(bit) {
2199
+ const resolved = this.constructor.resolve(bit);
2200
+ if (typeof this.bitfield === "bigint" && typeof resolved === "bigint") {
2201
+ return (this.bitfield & resolved) !== BigInt(0);
2202
+ }
2203
+ return (Number(this.bitfield) & Number(resolved)) !== 0;
2204
+ }
2205
+ /**
2206
+ * Checks whether this bitfield is exactly equal to the given bit value.
2207
+ *
2208
+ * @param bit The bit(s) to compare against.
2209
+ * @returns `true` if the resolved bit value is identical to this bitfield.
2210
+ *
2211
+ * @example
2212
+ * new Permissions(0n).equals(0n); // true
2213
+ */
2214
+ equals(bit) {
2215
+ return this.bitfield === this.constructor.resolve(bit);
2216
+ }
2217
+ /**
2218
+ * Checks whether this bitfield has *all* of the given bits set.
2219
+ *
2220
+ * @param bit The bit(s) to check for.
2221
+ * @returns `true` if every provided bit is set in this bitfield.
2222
+ *
2223
+ * @example
2224
+ * perms.has('SendMessage');
2225
+ * perms.has(['SendMessage', 'ViewChannel']); // true only if both are set
2226
+ */
2227
+ has(bit, ..._hasParams) {
2228
+ const resolvedBit = this.constructor.resolve(bit);
2229
+ if (typeof this.bitfield === "bigint" && typeof resolvedBit === "bigint") {
2230
+ return (this.bitfield & resolvedBit) === resolvedBit;
2231
+ }
2232
+ return (Number(this.bitfield) & Number(resolvedBit)) === Number(resolvedBit);
2233
+ }
2234
+ /**
2235
+ * Returns the flag names present in `bits` that are *missing* from this bitfield.
2236
+ *
2237
+ * @param bits The bits to check against.
2238
+ * @returns An array of flag name strings that are in `bits` but not in this bitfield.
2239
+ *
2240
+ * @example
2241
+ * // If perms only has SendMessage:
2242
+ * perms.missing(['SendMessage', 'ManageChannel']); // ['ManageChannel']
2243
+ */
2244
+ missing(bits, ...hasParams) {
2245
+ return new this.constructor(bits).remove(this).toArray(...hasParams);
2246
+ }
2247
+ /**
2248
+ * Freezes this BitField instance, making it immutable.
2249
+ * Subsequent calls to `add()` or `remove()` will return a new instance instead of mutating this one.
2250
+ *
2251
+ * @returns This instance, frozen.
2252
+ */
2253
+ freeze() {
2254
+ return Object.freeze(this);
2255
+ }
2256
+ /**
2257
+ * Adds one or more bits to this bitfield.
2258
+ * If the instance is frozen, returns a new BitField with the bits added.
2259
+ *
2260
+ * @param bits The bit(s) to add.
2261
+ * @returns This instance (or a new one if frozen), with the bits added.
2262
+ *
2263
+ * @example
2264
+ * perms.add('SendMessage', 'ViewChannel');
2265
+ */
2266
+ add(...bits) {
2267
+ let total = this.constructor.DefaultBit;
2268
+ for (const bit of bits) {
2269
+ const resolved = this.constructor.resolve(bit);
2270
+ if (typeof total === "bigint" && typeof resolved === "bigint") {
2271
+ total |= resolved;
2272
+ } else {
2273
+ total = Number(total) | Number(resolved);
2274
+ }
2275
+ }
2276
+ if (typeof this.bitfield === "bigint" && typeof total === "bigint") {
2277
+ if (Object.isFrozen(this)) return new this.constructor(this.bitfield | total);
2278
+ this.bitfield |= total;
2279
+ } else {
2280
+ if (Object.isFrozen(this))
2281
+ return new this.constructor(Number(this.bitfield) | Number(total));
2282
+ this.bitfield = Number(this.bitfield) | Number(total);
2283
+ }
2284
+ return this;
2285
+ }
2286
+ /**
2287
+ * Removes one or more bits from this bitfield.
2288
+ * If the instance is frozen, returns a new BitField with the bits removed.
2289
+ *
2290
+ * @param bits The bit(s) to remove.
2291
+ * @returns This instance (or a new one if frozen), with the bits cleared.
2292
+ *
2293
+ * @example
2294
+ * perms.remove('ManageChannel');
2295
+ */
2296
+ remove(...bits) {
2297
+ let total = this.constructor.DefaultBit;
2298
+ for (const bit of bits) {
2299
+ const resolved = this.constructor.resolve(bit);
2300
+ if (typeof total === "bigint" && typeof resolved === "bigint") {
2301
+ total |= resolved;
2302
+ } else {
2303
+ total = Number(total) | Number(resolved);
2304
+ }
2305
+ }
2306
+ if (typeof this.bitfield === "bigint" && typeof total === "bigint") {
2307
+ if (Object.isFrozen(this)) return new this.constructor(this.bitfield & ~total);
2308
+ this.bitfield &= ~total;
2309
+ } else {
2310
+ if (Object.isFrozen(this))
2311
+ return new this.constructor(Number(this.bitfield) & ~Number(total));
2312
+ this.bitfield = Number(this.bitfield) & ~Number(total);
2313
+ }
2314
+ return this;
2315
+ }
2316
+ /**
2317
+ * Serializes this bitfield to a plain object mapping each flag name to a boolean
2318
+ * indicating whether that flag is set.
2319
+ *
2320
+ * @returns A record of `{ [flagName]: boolean }` for all defined flags.
2321
+ *
2322
+ * @example
2323
+ * perms.serialize();
2324
+ * // { SendMessage: true, ManageChannel: false, ... }
2325
+ */
2326
+ serialize(...hasParams) {
2327
+ const serialized = {};
2328
+ for (const [flag, bit] of Object.entries(this.constructor.Flags)) {
2329
+ if (isNaN(Number(flag))) serialized[flag] = this.has(bit, ...hasParams);
2330
+ }
2331
+ return serialized;
2332
+ }
2333
+ /**
2334
+ * Returns an array of flag names that are set in this bitfield.
2335
+ *
2336
+ * @returns An array of string flag names.
2337
+ *
2338
+ * @example
2339
+ * perms.toArray(); // ['SendMessage', 'ViewChannel']
2340
+ */
2341
+ toArray(...hasParams) {
2342
+ return [...this[Symbol.iterator](...hasParams)];
2343
+ }
2344
+ /**
2345
+ * Returns the bitfield value as a JSON-safe primitive.
2346
+ * Numbers are returned as-is; bigints are converted to their string representation
2347
+ * to avoid JSON serialization errors.
2348
+ */
2349
+ toJSON() {
2350
+ return typeof this.bitfield === "number" ? this.bitfield : this.bitfield.toString();
2351
+ }
2352
+ /**
2353
+ * Returns the underlying numeric value of this bitfield.
2354
+ * Allows BitField instances to be used directly in arithmetic expressions.
2355
+ */
2356
+ valueOf() {
2357
+ return this.bitfield;
2358
+ }
2359
+ /**
2360
+ * Iterates over the names of all flags that are set in this bitfield.
2361
+ *
2362
+ * @example
2363
+ * for (const flag of perms) {
2364
+ * console.log(flag); // 'SendMessage', 'ViewChannel', etc.
2365
+ * }
2366
+ */
2367
+ *[Symbol.iterator](...hasParams) {
2368
+ for (const bitName of Object.keys(this.constructor.Flags)) {
2369
+ if (isNaN(Number(bitName)) && this.has(bitName, ...hasParams)) yield bitName;
2370
+ }
2371
+ }
2372
+ /**
2373
+ * Resolves a {@link BitFieldResolvable} into a raw `number | bigint`.
2374
+ *
2375
+ * Resolution rules (in order):
2376
+ * - `undefined` → `DefaultBit`
2377
+ * - A number or bigint matching `DefaultBit`'s type and >= 0 → returned as-is
2378
+ * - A `BitField` instance → its `.bitfield` value
2379
+ * - An array → each element resolved and OR'd together
2380
+ * - A numeric string → parsed as `BigInt` or `Number` depending on `DefaultBit`'s type
2381
+ * - A named string flag → looked up in `Flags`
2382
+ * - Anything else → throws `RangeError`
2383
+ *
2384
+ * @param bit The value to resolve.
2385
+ * @throws {RangeError} If the value cannot be resolved to a valid bit.
2386
+ */
2387
+ static resolve(bit) {
2388
+ const { DefaultBit } = this;
2389
+ if (bit === void 0) return DefaultBit;
2390
+ if (typeof DefaultBit === typeof bit && bit >= DefaultBit) return bit;
2391
+ if (bit instanceof _BitField) return bit.bitfield;
2392
+ if (Array.isArray(bit)) {
2393
+ return bit.map((b) => this.resolve(b)).reduce((prev, b) => {
2394
+ if (typeof prev === "bigint" && typeof b === "bigint") return prev | b;
2395
+ return Number(prev) | Number(b);
2396
+ }, DefaultBit);
2397
+ }
2398
+ if (typeof bit === "string") {
2399
+ if (!isNaN(Number(bit))) return typeof DefaultBit === "bigint" ? BigInt(bit) : Number(bit);
2400
+ if (this.Flags[bit] !== void 0) return this.Flags[bit];
2401
+ }
2402
+ throw new RangeError(`Invalid bitfield flag or number: ${String(bit)}`);
2403
+ }
2404
+ };
2405
+
1996
2406
  // src/utils/permissions.ts
1997
2407
  var PermissionFlags = {
1998
2408
  // Server permissions
@@ -2036,26 +2446,26 @@ var PermissionFlags = {
2036
2446
  // Grant all
2037
2447
  GrantAllSafe: 0x000fffffffffffffn
2038
2448
  };
2039
- var Permissions = class {
2040
- /**
2041
- * Converts a string, BigInt, or array of strings into a single BigInt
2042
- */
2043
- static resolve(permission) {
2044
- if (typeof permission === "bigint") return permission;
2045
- if (typeof permission === "string") {
2046
- return PermissionFlags[permission] ?? 0n;
2047
- }
2048
- if (Array.isArray(permission)) {
2049
- return permission.reduce((acc, p) => acc | this.resolve(p), 0n);
2050
- }
2051
- return 0n;
2449
+ var Permissions = class extends BitField {
2450
+ static Flags = PermissionFlags;
2451
+ static DefaultBit = 0n;
2452
+ static resolve(bit) {
2453
+ return super.resolve(bit);
2052
2454
  }
2053
- /**
2054
- * Checks if a specific permission bit exists
2055
- */
2056
- static has(totalPermissions, permissionToCheck) {
2057
- const resolvedCheck = this.resolve(permissionToCheck);
2058
- return (totalPermissions & resolvedCheck) === resolvedCheck;
2455
+ has(bit) {
2456
+ return super.has(bit);
2457
+ }
2458
+ any(bit) {
2459
+ return super.any(bit);
2460
+ }
2461
+ missing(bits) {
2462
+ return super.missing(bits);
2463
+ }
2464
+ add(...bits) {
2465
+ return super.add(...bits);
2466
+ }
2467
+ remove(...bits) {
2468
+ return super.remove(...bits);
2059
2469
  }
2060
2470
  };
2061
2471
 
@@ -2070,7 +2480,7 @@ var ChannelManager = class extends BaseManager {
2070
2480
  super(client, limit);
2071
2481
  }
2072
2482
  extractId(data) {
2073
- return data._id ?? data.id;
2483
+ return data._id;
2074
2484
  }
2075
2485
  construct(data) {
2076
2486
  return createChannel(this.client, data);
@@ -2163,8 +2573,14 @@ var ChannelManager = class extends BaseManager {
2163
2573
  else payload.description = options.description;
2164
2574
  }
2165
2575
  if (options.icon !== void 0) {
2166
- if (options.icon === null) remove.push("Icon");
2167
- else payload.icon = options.icon;
2576
+ if (options.icon === null) {
2577
+ remove.push("Icon");
2578
+ } else {
2579
+ const resolvedIcon = await resolveAttachment(this.client.rest, options.icon, "icons");
2580
+ if (resolvedIcon !== void 0) {
2581
+ payload.icon = resolvedIcon;
2582
+ }
2583
+ }
2168
2584
  }
2169
2585
  if (remove.length > 0) payload.remove = remove;
2170
2586
  if (Object.keys(payload).length === 0) return this.fetch(channel);
@@ -2249,7 +2665,7 @@ var ChannelManager = class extends BaseManager {
2249
2665
  * await client.channels.pin("CHANNEL_ID", "MESSAGE_ID");
2250
2666
  */
2251
2667
  async pin(id, messageId) {
2252
- await this.client.rest.post(`/channels/${id}/pins/${messageId}`);
2668
+ await this.client.rest.post(`/channels/${id}/messages/${messageId}/pin`);
2253
2669
  }
2254
2670
  /**
2255
2671
  * Unpin a message
@@ -2279,7 +2695,7 @@ var ChannelManager = class extends BaseManager {
2279
2695
  if ("id" in msg) return msg.id;
2280
2696
  throw new TypeError("Invalid MessageResolvable provided. Expected a Message object or a string ID/Mention.");
2281
2697
  });
2282
- await this.client.rest.delete(`/channels/${id}/messages/bulk`, { messages: messageIds });
2698
+ await this.client.rest.delete(`/channels/${id}/messages/bulk`, { ids: messageIds });
2283
2699
  }
2284
2700
  };
2285
2701
 
@@ -2378,20 +2794,20 @@ var Member = class extends Base {
2378
2794
  canRecieve = false;
2379
2795
  // Member roles manager
2380
2796
  roles;
2381
- constructor(client, data) {
2382
- super(client, { _id: data.user._id });
2383
- this.serverId = data.serverId || data.server_id;
2384
- this.joinedAt = new Date(data.joinedAt || data.joined_at);
2797
+ constructor(client, data, serverId) {
2798
+ super(client, { _id: data._id?.user });
2799
+ this.serverId = data._id?.server ?? serverId;
2800
+ this.joinedAt = new Date(data.joined_at);
2385
2801
  this.roles = new MemberRoleManager(this);
2386
2802
  this._patch(data);
2387
2803
  }
2388
2804
  _patch(data) {
2389
2805
  if (data.nickname !== void 0) this.nickname = data.nickname;
2390
- if (data.avatar !== void 0) this.avatar = data.avatar;
2806
+ if (data.avatar !== void 0) this.avatar = data.avatar ? new Attachment(this.client, data.avatar) : null;
2391
2807
  if (data.roles !== void 0) this._roles = data.roles;
2392
2808
  if (data.timeout !== void 0) this.timeout = data.timeout ? new Date(data.timeout) : null;
2393
- if (data.can_publish !== void 0) this.canPublish = data.canPublish;
2394
- if (data.can_recieve !== void 0) this.canRecieve = data.canRecieve;
2809
+ if (data.can_publish !== void 0) this.canPublish = data.can_publish;
2810
+ if (data.can_receive !== void 0) this.canRecieve = data.can_receive;
2395
2811
  }
2396
2812
  /**
2397
2813
  * Get member role IDs
@@ -2410,15 +2826,15 @@ var Member = class extends Base {
2410
2826
  /** Calculates the member's total permissions using BigInt */
2411
2827
  get permissions() {
2412
2828
  const server = this.server;
2413
- if (!server) return 0n;
2829
+ if (!server) return new Permissions(0n);
2830
+ if (server.ownerId === this.id) {
2831
+ return new Permissions(PermissionFlags.GrantAllSafe);
2832
+ }
2414
2833
  let totalPerms = server.defaultPermissions ?? 0n;
2415
2834
  for (const role of this.roles.cache.values()) {
2416
- totalPerms |= BigInt(role.permissions);
2417
- }
2418
- if (server.ownerId === this.id) {
2419
- return PermissionFlags.GrantAllSafe;
2835
+ totalPerms |= BigInt(role.permissions.bitfield);
2420
2836
  }
2421
- return totalPerms;
2837
+ return new Permissions(totalPerms);
2422
2838
  }
2423
2839
  /** Get avatar URL for this member, or null if they don't have one.
2424
2840
  * @example
@@ -2482,10 +2898,6 @@ var Member = class extends Base {
2482
2898
  async setNickname(nickname) {
2483
2899
  return this.edit({ nickname });
2484
2900
  }
2485
- /** Checks if the member has a specific permission */
2486
- hasPermission(permission) {
2487
- return Permissions.has(this.permissions, permission);
2488
- }
2489
2901
  /**
2490
2902
  * Edit this member.
2491
2903
  * @param options The options to edit the member with (nickname, roles, timeout, etc.)
@@ -2540,17 +2952,14 @@ var MemberManager = class extends BaseManager {
2540
2952
  * @internal
2541
2953
  */
2542
2954
  extractId(data) {
2543
- return data.user_id ?? data.id ?? (typeof data._id === "string" ? data._id : data._id?.user);
2955
+ return data._id?.user;
2544
2956
  }
2545
2957
  /**
2546
2958
  * Tell BaseManager how to build a Member
2547
2959
  * @internal
2548
2960
  */
2549
2961
  construct(data) {
2550
- if (!data.server_id && !data.serverId) {
2551
- data.serverId = this.server.id;
2552
- }
2553
- return new Member(this.client, data);
2962
+ return new Member(this.client, data, this.server.id);
2554
2963
  }
2555
2964
  /**
2556
2965
  * Resolve a string or mention to Member
@@ -2609,23 +3018,22 @@ var MemberManager = class extends BaseManager {
2609
3018
  * const onlineMembers = await server.members.fetchMany({ exclude_offline: true });
2610
3019
  */
2611
3020
  async fetchMany(options = {}) {
2612
- const params = new URLSearchParams();
2613
- if (options.exclude_offline !== void 0) {
2614
- params.append("exclude_offline", options.exclude_offline.toString());
3021
+ const query = {};
3022
+ if (options.excludeOffline !== void 0) {
3023
+ query.exclude_offline = options.excludeOffline;
2615
3024
  }
2616
- const queryString = params.toString();
2617
- const endpoint = `/servers/${this.server.id}/members${queryString ? `?${queryString}` : ""}`;
2618
- const data = await this.client.rest.get(endpoint);
2619
- if (data.users && Array.isArray(data.users)) {
3025
+ const data = await this.client.rest.get(`/servers/${this.server.id}/members`, query);
3026
+ if (data.users) {
2620
3027
  for (const userData of data.users) {
2621
3028
  this.client.users._add(userData);
2622
3029
  }
2623
3030
  }
2624
3031
  const fetched = new Collection();
2625
- const rawMembers = data.members || (Array.isArray(data) ? data : []);
2626
- for (const rawMember of rawMembers) {
2627
- const member = this._add(rawMember);
2628
- fetched.set(member.id, member);
3032
+ if (data.members) {
3033
+ for (const rawMember of data.members) {
3034
+ const member = this._add(rawMember);
3035
+ fetched.set(member.id, member);
3036
+ }
2629
3037
  }
2630
3038
  return fetched;
2631
3039
  }
@@ -2728,11 +3136,17 @@ var ServerChannelManager = class {
2728
3136
  async create(options) {
2729
3137
  if (!options.name) throw new Error("A channel name must be provided.");
2730
3138
  const payload = {
2731
- name: options.name,
2732
- type: options.type ?? "Text",
2733
- description: options.description,
2734
- nsfw: options.nsfw ?? false
3139
+ name: options.name
2735
3140
  };
3141
+ if (options.nsfw !== void 0) {
3142
+ payload.nsfw = options.nsfw;
3143
+ }
3144
+ if (options.type !== void 0) {
3145
+ payload.type = options.type;
3146
+ }
3147
+ if (options.description !== void 0) {
3148
+ payload.description = options.description;
3149
+ }
2736
3150
  if (options.type === "Voice" && options.voice?.max_users) {
2737
3151
  payload.voice = { max_users: options.voice.max_users };
2738
3152
  }
@@ -2752,7 +3166,8 @@ var Role = class extends Base {
2752
3166
  color = null;
2753
3167
  hoist = false;
2754
3168
  rank = 0;
2755
- permissions = 0n;
3169
+ icon = null;
3170
+ _permissions = 0n;
2756
3171
  constructor(client, data, serverId) {
2757
3172
  super(client, data);
2758
3173
  this.serverId = serverId;
@@ -2764,19 +3179,20 @@ var Role = class extends Base {
2764
3179
  */
2765
3180
  _patch(data) {
2766
3181
  if (data.name !== void 0) this.name = data.name;
2767
- if (data.color !== void 0) this.color = data.color;
3182
+ if (data.colour !== void 0) this.color = data.colour;
2768
3183
  if (data.hoist !== void 0) this.hoist = data.hoist;
2769
3184
  if (data.rank !== void 0) this.rank = data.rank;
3185
+ if (data.icon !== void 0) this.icon = data.icon !== null ? new Attachment(this.client, data.icon) : null;
2770
3186
  if (data.permissions !== void 0) {
2771
3187
  try {
2772
3188
  if (typeof data.permissions === "object" && data.permissions !== null) {
2773
- const allowPerms = data.permissions.a ?? data.permissions[0] ?? 0;
2774
- this.permissions = BigInt(allowPerms);
3189
+ const allowPerms = data.permissions.a ?? 0;
3190
+ this._permissions = BigInt(allowPerms);
2775
3191
  } else {
2776
- this.permissions = BigInt(data.permissions);
3192
+ this._permissions = BigInt(data.permissions);
2777
3193
  }
2778
3194
  } catch {
2779
- this.permissions = 0n;
3195
+ this._permissions = 0n;
2780
3196
  }
2781
3197
  }
2782
3198
  }
@@ -2788,12 +3204,10 @@ var Role = class extends Base {
2788
3204
  return this.client.servers.cache.get(this.serverId);
2789
3205
  }
2790
3206
  /**
2791
- * Checks whether this role has a specific permission.
2792
- * @param permission The permission to check for.
2793
- * @returns True if the role has the permission.
3207
+ * Permissions for this role
2794
3208
  */
2795
- hasPermission(permission) {
2796
- return Permissions.has(this.permissions, permission);
3209
+ get permissions() {
3210
+ return new Permissions(this._permissions);
2797
3211
  }
2798
3212
  /**
2799
3213
  * Fetches this role directly from the API to ensure data is up to date.
@@ -2821,10 +3235,10 @@ var Role = class extends Base {
2821
3235
  * @throws {Error} If the API request fails (e.g., lack of permissions).
2822
3236
  * @example
2823
3237
  * // Change the role's name and color
2824
- * await role.edit({ name: "Senior Admin", colour: "#FFD700" });
3238
+ * await role.edit({ name: "Senior Admin", color: "#FFD700" });
2825
3239
  *
2826
3240
  * // Remove the custom color from the role
2827
- * await role.edit({ colour: null });
3241
+ * await role.edit({ color: null });
2828
3242
  */
2829
3243
  async edit(options) {
2830
3244
  let server = this.server;
@@ -2883,6 +3297,73 @@ var Role = class extends Base {
2883
3297
  await server.roles.setRanks(filteredRoles);
2884
3298
  return this;
2885
3299
  }
3300
+ /**
3301
+ * Change the name for this role
3302
+ * @param name The new name for the role
3303
+ * @returns A promise that resolves to this updated Role object.
3304
+ * @throws {Error} If API request fails.
3305
+ * @example
3306
+ * // Change the role's name
3307
+ * await role.setName("New Role Name");
3308
+ * console.log(`Role's new name: ${role.name}`);
3309
+ */
3310
+ async setName(name) {
3311
+ return await this.edit({ name });
3312
+ }
3313
+ /**
3314
+ * Change the color for this role, it can be a HEX or CSS colours
3315
+ * @param {[string]} color The new color for the role
3316
+ * @returns A promise that resolves to this updated Role object.
3317
+ * @throws {Error} If API request fails
3318
+ * @example
3319
+ * // Change the role's color
3320
+ * await role.setColour("#FF0000");
3321
+ * console.log(`Role's new color: ${role.color}`);
3322
+ *
3323
+ * // Use CSS color linear-graident
3324
+ * await role.setColour("linear-gradient(90deg, #FF0000, #0000FF)");
3325
+ * console.log(`Role's new color: ${role.color}`);
3326
+ *
3327
+ * // Remove the custom color from the role
3328
+ * await role.setColour(null);
3329
+ * console.log(`Role's color removed, current color: ${role.color}`);
3330
+ */
3331
+ async setColor(color) {
3332
+ return await this.edit({ color });
3333
+ }
3334
+ /**
3335
+ * Edit the icon of this role
3336
+ * @param icon Autumn ID for the new icon, or null to remove the custom icon
3337
+ * @returns A promise that resolves to this updated Role object.
3338
+ * @throws {Error} If API request fails
3339
+ * @example
3340
+ * // Set a new icon for the role
3341
+ * await role.setIcon("AUTUMN_ID_FOR_ICON");
3342
+ * console.log(`Role's new icon: ${role.icon}`);
3343
+ *
3344
+ * // Use AttachmentBuilder to upload a new icon file
3345
+ * import { readFile } from "node:fs/promises";
3346
+ * const iconFile = await readFile("./a.jpg");
3347
+ * const attachment = new AttachmentBuilder(iconFile, "a.jpg");
3348
+ * await role.setIcon(attachment);
3349
+ * console.log(`Role's new icon: ${role.icon}`);
3350
+ */
3351
+ async setIcon(icon) {
3352
+ return await this.edit({ icon });
3353
+ }
3354
+ /**
3355
+ * Change the hoist status for this role
3356
+ * @param hoist The new hoist status for the role
3357
+ * @returns A promise that resolves to this updated Role object.
3358
+ * @throws {Error} If API request fails
3359
+ * @example
3360
+ * // Enable hoisting for the role
3361
+ * await role.setHoist(true);
3362
+ * console.log(`Role is now hoisted: ${role.hoist}`);
3363
+ */
3364
+ async setHoist(hoist) {
3365
+ return await this.edit({ hoist });
3366
+ }
2886
3367
  /**
2887
3368
  * Customizer for Node.js `console.log` and `util.inspect`.
2888
3369
  * Hides the cyclic client reference and raw serverId for a cleaner output.
@@ -2908,7 +3389,7 @@ var RoleManager = class extends BaseManager {
2908
3389
  * Tell BaseManager how to find the ID for Roles
2909
3390
  */
2910
3391
  extractId(data) {
2911
- return data._id ?? data.id;
3392
+ return data._id;
2912
3393
  }
2913
3394
  /**
2914
3395
  * Tell BaseManager how to build a Role
@@ -2924,7 +3405,7 @@ var RoleManager = class extends BaseManager {
2924
3405
  * @returns The newly created or updated Role object.
2925
3406
  */
2926
3407
  _add(data, idParam) {
2927
- const id = idParam ?? data._id ?? data.id;
3408
+ const id = idParam ?? data._id;
2928
3409
  const existing = this.cache.get(id);
2929
3410
  if (existing) {
2930
3411
  existing._patch(data);
@@ -2987,7 +3468,7 @@ var RoleManager = class extends BaseManager {
2987
3468
  name: options.name
2988
3469
  };
2989
3470
  const data = await this.client.rest.post(`/servers/${this.server.id}/roles`, payload);
2990
- return this._add(data);
3471
+ return this._add(data.role);
2991
3472
  }
2992
3473
  /**
2993
3474
  * Fetches a Role from the API or resolves it from the local cache.
@@ -3020,7 +3501,7 @@ var RoleManager = class extends BaseManager {
3020
3501
  }
3021
3502
  /**
3022
3503
  * Edits an existing role in the server.
3023
- * @param role The RoleResolvable to edit.
3504
+ * @param role The {@link RoleResolvable} to edit.
3024
3505
  * @param options The fields to update.
3025
3506
  * @returns A promise that resolves to the updated Role.
3026
3507
  * @throws {TypeError} If invalid options or RoleResolvable are provided.
@@ -3041,11 +3522,21 @@ var RoleManager = class extends BaseManager {
3041
3522
  const remove = [];
3042
3523
  if (options.name !== void 0) payload.name = options.name;
3043
3524
  if (options.hoist !== void 0) payload.hoist = options.hoist;
3044
- if (options.colour !== void 0) {
3045
- if (options.colour === null) {
3525
+ if (options.color !== void 0) {
3526
+ if (options.color === null) {
3046
3527
  remove.push("Colour");
3047
3528
  } else {
3048
- payload.colour = options.colour;
3529
+ payload.colour = options.color;
3530
+ }
3531
+ }
3532
+ if (options.icon !== void 0) {
3533
+ if (options.icon === null) {
3534
+ remove.push("Icon");
3535
+ } else {
3536
+ const resolvedIcon = await resolveAttachment(this.client.rest, options.icon, "icons");
3537
+ if (resolvedIcon !== void 0) {
3538
+ payload.icon = resolvedIcon;
3539
+ }
3049
3540
  }
3050
3541
  }
3051
3542
  if (remove.length > 0) {
@@ -3054,7 +3545,8 @@ var RoleManager = class extends BaseManager {
3054
3545
  if (Object.keys(payload).length === 0) {
3055
3546
  return this.fetch(id);
3056
3547
  }
3057
- const data = await this.client.rest.patch(`/servers/${this.server.id}/roles/${id}`, payload);
3548
+ const endpoint = `/servers/${this.server.id}/roles/${id}`;
3549
+ const data = await this.client.rest.patch(endpoint, payload);
3058
3550
  return this._add(data, id);
3059
3551
  }
3060
3552
  /**
@@ -3130,7 +3622,7 @@ var RoleManager = class extends BaseManager {
3130
3622
  const payload = {
3131
3623
  ranks: mappedIds
3132
3624
  };
3133
- const data = await this.client.rest.put(`/servers/${this.server.id}/roles`, payload);
3625
+ const data = await this.client.rest.patch(`/servers/${this.server.id}/roles/ranks`, payload);
3134
3626
  this.server._patch(data);
3135
3627
  return this.server;
3136
3628
  }
@@ -3142,7 +3634,7 @@ var ServerInvite = class {
3142
3634
  creatorId;
3143
3635
  channelId;
3144
3636
  constructor(data) {
3145
- this.code = data._id ?? data.code;
3637
+ this.code = data._id;
3146
3638
  this.creatorId = data.creator;
3147
3639
  this.channelId = data.channel;
3148
3640
  }
@@ -3159,7 +3651,7 @@ var ServerInviteManager = class extends BaseManager {
3159
3651
  this.server = server;
3160
3652
  }
3161
3653
  extractId(data) {
3162
- return data._id ?? data.code;
3654
+ return data._id;
3163
3655
  }
3164
3656
  construct(data) {
3165
3657
  return new ServerInvite(data);
@@ -3169,9 +3661,8 @@ var ServerInviteManager = class extends BaseManager {
3169
3661
  */
3170
3662
  async fetch() {
3171
3663
  const data = await this.client.rest.get(`/servers/${this.server.id}/invites`);
3172
- const rawInvites = Array.isArray(data) ? data : [];
3173
3664
  const fetched = new Collection();
3174
- for (const raw of rawInvites) {
3665
+ for (const raw of data) {
3175
3666
  const invite = this._add(raw);
3176
3667
  fetched.set(invite.code, invite);
3177
3668
  }
@@ -3184,7 +3675,7 @@ var ServerBan = class {
3184
3675
  userId;
3185
3676
  reason;
3186
3677
  constructor(data) {
3187
- this.userId = data._id?.user ?? data.id;
3678
+ this.userId = data._id?.user;
3188
3679
  this.reason = data.reason ?? null;
3189
3680
  }
3190
3681
  _patch(data) {
@@ -3291,7 +3782,7 @@ var Server = class extends Base {
3291
3782
  ownerId;
3292
3783
  analytics = false;
3293
3784
  banner = null;
3294
- categories = [];
3785
+ categories = null;
3295
3786
  description = null;
3296
3787
  discoverable = false;
3297
3788
  flags = 0;
@@ -3344,13 +3835,6 @@ var Server = class extends Base {
3344
3835
  this.roles._add({ id, ...roleData });
3345
3836
  }
3346
3837
  }
3347
- if (data.emojis !== void 0) {
3348
- if (Array.isArray(data.emojis)) {
3349
- for (const emoji of data.emojis) {
3350
- this.emojis._add(emoji);
3351
- }
3352
- }
3353
- }
3354
3838
  if (clear && Array.isArray(clear)) {
3355
3839
  for (const field of clear) {
3356
3840
  switch (field) {
@@ -3398,7 +3882,7 @@ var ServerManager = class extends BaseManager {
3398
3882
  * Tell BaseManager how to find the ID for Servers
3399
3883
  */
3400
3884
  extractId(data) {
3401
- return data._id ?? data.id;
3885
+ return data._id;
3402
3886
  }
3403
3887
  /**
3404
3888
  * Tell BaseManager how to build a Server
@@ -3439,21 +3923,19 @@ var ServerManager = class extends BaseManager {
3439
3923
  payload.system_messages = {};
3440
3924
  const sm = options.systemMessages;
3441
3925
  if (sm.userJoined !== void 0) {
3442
- if (sm.userJoined === null) remove.push("SystemMessageUserJoined");
3443
- else payload.system_messages.user_joined = sm.userJoined;
3926
+ payload.system_messages.user_joined = sm.userJoined;
3444
3927
  }
3445
3928
  if (sm.userLeft !== void 0) {
3446
- if (sm.userLeft === null) remove.push("SystemMessageUserLeft");
3447
- else payload.system_messages.user_left = sm.userLeft;
3929
+ payload.system_messages.user_left = sm.userLeft;
3448
3930
  }
3449
3931
  if (sm.userKicked !== void 0) {
3450
- if (sm.userKicked === null) remove.push("SystemMessageUserKicked");
3451
- else payload.system_messages.user_kicked = sm.userKicked;
3932
+ payload.system_messages.user_kicked = sm.userKicked;
3452
3933
  }
3453
3934
  if (sm.userBanned !== void 0) {
3454
- if (sm.userBanned === null) remove.push("SystemMessageUserBanned");
3455
- else payload.system_messages.user_banned = sm.userBanned;
3935
+ payload.system_messages.user_banned = sm.userBanned;
3456
3936
  }
3937
+ } else if (options.systemMessages === null) {
3938
+ remove.push("SystemMessages");
3457
3939
  }
3458
3940
  if (options.categories !== void 0) payload.categories = options.categories;
3459
3941
  if (options.analytics !== void 0) payload.analytics = options.analytics;
@@ -3476,7 +3958,7 @@ var UserManager = class extends BaseManager {
3476
3958
  * Tell BaseManager how to find the ID for Users
3477
3959
  */
3478
3960
  extractId(data) {
3479
- return data._id ?? data.id;
3961
+ return data._id;
3480
3962
  }
3481
3963
  /**
3482
3964
  * Tell BaseManager how to build a User
@@ -3611,7 +4093,7 @@ var UserManager = class extends BaseManager {
3611
4093
  if (Object.keys(payload).length === 0) {
3612
4094
  return this.fetch("@me");
3613
4095
  }
3614
- const data = await this.client.rest.patch(`/users/@me`, payload);
4096
+ const data = await this.client.rest.patch(`/users/${this.client.user?.id}`, payload);
3615
4097
  return this._add(data);
3616
4098
  }
3617
4099
  /**
@@ -3771,13 +4253,18 @@ var EmbedBuilder = class {
3771
4253
  return { ...this.data };
3772
4254
  }
3773
4255
  };
4256
+
4257
+ // src/index.ts
4258
+ var API = __toESM(require("stoat-api"), 1);
3774
4259
  // Annotate the CommonJS export names for ESM import in node:
3775
4260
  0 && (module.exports = {
4261
+ API,
3776
4262
  Attachment,
4263
+ AttachmentBuilder,
3777
4264
  Base,
3778
4265
  BaseChannel,
4266
+ BitField,
3779
4267
  ChannelManager,
3780
- ChannelType,
3781
4268
  Client,
3782
4269
  ClientUser,
3783
4270
  Collection,
@@ -3807,8 +4294,6 @@ var EmbedBuilder = class {
3807
4294
  TextChannel,
3808
4295
  UnknownChannel,
3809
4296
  User,
3810
- UserManager,
3811
- UserPresence,
3812
- UserRelationship
4297
+ UserManager
3813
4298
  });
3814
4299
  //# sourceMappingURL=index.cjs.map