@impulsedev/chameleon 1.7.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,40 @@
1
+ import {
2
+ ActionRowBuilder,
3
+ ButtonBuilder,
4
+ ButtonStyle,
5
+ Colors,
6
+ ComponentType,
7
+ EmbedBuilder,
8
+ ModalBuilder,
9
+ SelectMenuBuilder,
10
+ TextInputBuilder,
11
+ buildAutoModRule,
12
+ buildChannel,
13
+ buildEmoji,
14
+ buildEntitlement,
15
+ buildGuild,
16
+ buildIntegration,
17
+ buildInteraction,
18
+ buildInvite,
19
+ buildMember,
20
+ buildMessage,
21
+ buildRole,
22
+ buildScheduledEvent,
23
+ buildStageInstance,
24
+ buildSticker,
25
+ buildStickerItem,
26
+ buildUser,
27
+ buildVoiceState,
28
+ buildWebhook,
29
+ resolveChannel,
30
+ resolveGuild,
31
+ resolveRole,
32
+ resolveUser,
33
+ serializeComponent,
34
+ toCamelCase,
35
+ toSnakeCase
36
+ } from "./chunk-G4SUOXGV.js";
37
+
1
38
  // src/types/user/index.ts
2
39
  var UserFlag = {
3
40
  STAFF: 1 << 0,
@@ -462,26 +499,6 @@ var AutoModerationActionType = {
462
499
  BLOCK_MEMBER_INTERACTION: 4
463
500
  };
464
501
 
465
- // src/types/components/index.ts
466
- var ComponentType = {
467
- ACTION_ROW: 1,
468
- BUTTON: 2,
469
- STRING_SELECT: 3,
470
- TEXT_INPUT: 4,
471
- USER_SELECT: 5,
472
- ROLE_SELECT: 6,
473
- MENTIONABLE_SELECT: 7,
474
- CHANNEL_SELECT: 8
475
- };
476
- var ButtonStyle = {
477
- PRIMARY: 1,
478
- SECONDARY: 2,
479
- SUCCESS: 3,
480
- DANGER: 4,
481
- LINK: 5,
482
- PREMIUM: 6
483
- };
484
-
485
502
  // src/types/entitlement/index.ts
486
503
  var EntitlementType = {
487
504
  PURCHASE: 1,
@@ -588,49 +605,97 @@ var WebhookType = {
588
605
  APPLICATION: 3
589
606
  };
590
607
 
608
+ // src/utils/collection.ts
609
+ var Collection = class _Collection extends Map {
610
+ first() {
611
+ return this.values().next().value;
612
+ }
613
+ last() {
614
+ const arr = Array.from(this.values());
615
+ return arr[arr.length - 1];
616
+ }
617
+ random() {
618
+ const arr = Array.from(this.values());
619
+ return arr[Math.floor(Math.random() * arr.length)];
620
+ }
621
+ find(fn) {
622
+ for (const [key, val] of this) {
623
+ if (fn(val, key, this)) return val;
624
+ }
625
+ return void 0;
626
+ }
627
+ filter(fn) {
628
+ const results = new _Collection();
629
+ for (const [key, val] of this) {
630
+ if (fn(val, key, this)) results.set(key, val);
631
+ }
632
+ return results;
633
+ }
634
+ map(fn) {
635
+ const results = [];
636
+ for (const [key, val] of this) {
637
+ results.push(fn(val, key, this));
638
+ }
639
+ return results;
640
+ }
641
+ some(fn) {
642
+ for (const [key, val] of this) {
643
+ if (fn(val, key, this)) return true;
644
+ }
645
+ return false;
646
+ }
647
+ every(fn) {
648
+ for (const [key, val] of this) {
649
+ if (!fn(val, key, this)) return false;
650
+ }
651
+ return true;
652
+ }
653
+ reduce(fn, initialValue) {
654
+ let accumulator;
655
+ let init = false;
656
+ if (initialValue !== void 0) {
657
+ accumulator = initialValue;
658
+ init = true;
659
+ }
660
+ for (const [key, val] of this) {
661
+ if (!init) {
662
+ accumulator = val;
663
+ init = true;
664
+ } else {
665
+ accumulator = fn(accumulator, val, key, this);
666
+ }
667
+ }
668
+ return accumulator;
669
+ }
670
+ toArray() {
671
+ return Array.from(this.values());
672
+ }
673
+ };
674
+
591
675
  // src/utils/tongue.ts
592
- var Tongue = class {
593
- map;
676
+ var Tongue = class extends Collection {
594
677
  max;
595
678
  constructor(maxSize = Infinity) {
596
- this.map = /* @__PURE__ */ new Map();
679
+ super();
597
680
  this.max = maxSize;
598
681
  }
599
682
  get(key) {
600
- if (!this.map.has(key)) return void 0;
601
- const val = this.map.get(key);
602
- this.map.delete(key);
603
- this.map.set(key, val);
683
+ if (!super.has(key)) return void 0;
684
+ const val = super.get(key);
685
+ super.delete(key);
686
+ super.set(key, val);
604
687
  return val;
605
688
  }
606
689
  set(key, val) {
607
- if (this.map.has(key)) {
608
- this.map.delete(key);
609
- } else if (this.map.size >= this.max) {
610
- const firstKey = this.map.keys().next().value;
611
- if (firstKey !== void 0) this.map.delete(firstKey);
690
+ if (super.has(key)) {
691
+ super.delete(key);
692
+ } else if (this.size >= this.max) {
693
+ const firstKey = this.keys().next().value;
694
+ if (firstKey !== void 0) super.delete(firstKey);
612
695
  }
613
- this.map.set(key, val);
696
+ super.set(key, val);
614
697
  return this;
615
698
  }
616
- has(key) {
617
- return this.map.has(key);
618
- }
619
- delete(key) {
620
- return this.map.delete(key);
621
- }
622
- clear() {
623
- this.map.clear();
624
- }
625
- get size() {
626
- return this.map.size;
627
- }
628
- values() {
629
- return this.map.values();
630
- }
631
- keys() {
632
- return this.map.keys();
633
- }
634
699
  };
635
700
 
636
701
  // src/client/store.ts
@@ -647,19 +712,21 @@ var TongueStore = class {
647
712
  scheduledEvents;
648
713
  autoModRules;
649
714
  integrations;
715
+ voiceStates;
650
716
  constructor(options) {
651
- this.guilds = new Tongue(options?.guilds ?? Infinity);
652
- this.roles = new Tongue(options?.roles ?? Infinity);
653
- this.channels = new Tongue(options?.channels ?? Infinity);
717
+ this.guilds = new Tongue(options?.guilds ?? 100);
718
+ this.roles = new Tongue(options?.roles ?? 5e3);
719
+ this.channels = new Tongue(options?.channels ?? 5e3);
654
720
  this.members = new Tongue(options?.members ?? 1e3);
655
721
  this.messages = new Tongue(options?.messages ?? 100);
656
- this.users = new Tongue(options?.users ?? Infinity);
657
- this.emojis = new Tongue(options?.emojis ?? Infinity);
658
- this.stickers = new Tongue(options?.stickers ?? Infinity);
659
- this.stageInstances = new Tongue(options?.stageInstances ?? Infinity);
660
- this.scheduledEvents = new Tongue(options?.scheduledEvents ?? Infinity);
661
- this.autoModRules = new Tongue(options?.autoModRules ?? Infinity);
662
- this.integrations = new Tongue(options?.integrations ?? Infinity);
722
+ this.users = new Tongue(options?.users ?? 1e4);
723
+ this.emojis = new Tongue(options?.emojis ?? 5e3);
724
+ this.stickers = new Tongue(options?.stickers ?? 5e3);
725
+ this.stageInstances = new Tongue(options?.stageInstances ?? 1e3);
726
+ this.scheduledEvents = new Tongue(options?.scheduledEvents ?? 1e3);
727
+ this.autoModRules = new Tongue(options?.autoModRules ?? 1e3);
728
+ this.integrations = new Tongue(options?.integrations ?? 1e3);
729
+ this.voiceStates = new Tongue(options?.voiceStates ?? 5e3);
663
730
  }
664
731
  static memberKey(guildId, userId) {
665
732
  return `${guildId}_${userId}`;
@@ -681,7 +748,7 @@ var Bucket = class {
681
748
  resetTimestamp = 0;
682
749
  promiseQueue = Promise.resolve();
683
750
  async queue(fn) {
684
- return new Promise((resolve2, reject) => {
751
+ return new Promise((resolve4, reject) => {
685
752
  this.promiseQueue = this.promiseQueue.then(async () => {
686
753
  while (true) {
687
754
  if (this.remaining <= 0 && Date.now() < this.resetTimestamp) {
@@ -690,7 +757,7 @@ var Bucket = class {
690
757
  this.remaining--;
691
758
  try {
692
759
  const res = await fn();
693
- resolve2(res);
760
+ resolve4(res);
694
761
  break;
695
762
  } catch (e) {
696
763
  if (e instanceof RateLimitError) {
@@ -710,13 +777,13 @@ var RateLimiter = class {
710
777
  routeToBucket = /* @__PURE__ */ new Map();
711
778
  buckets = /* @__PURE__ */ new Map();
712
779
  getRoute(method, endpoint) {
713
- const path2 = endpoint.replace(/\/([a-z-]+)\/(?:[0-9]{17,19})/g, (match, p1) => {
780
+ const path4 = endpoint.replace(/\/([a-z-]+)\/(?:[0-9]{17,19})/g, (match, p1) => {
714
781
  if (["channels", "guilds", "webhooks"].includes(p1)) {
715
782
  return match;
716
783
  }
717
784
  return `/${p1}/:id`;
718
785
  });
719
- const reactionRoute = path2.replace(/\/reactions\/[^/]+\/?(@me|[0-9]{17,19})?/g, "/reactions/:emoji/:id");
786
+ const reactionRoute = path4.replace(/\/reactions\/[^/]+\/?(@me|[0-9]{17,19})?/g, "/reactions/:emoji/:id");
720
787
  return `${method} ${reactionRoute}`;
721
788
  }
722
789
  async execute(method, endpoint, requestFn) {
@@ -783,8 +850,8 @@ var ChameleonREST = class {
783
850
  * Internal generic request handler that doesn't throw, returning `{ ok: boolean, ... }` shape
784
851
  */
785
852
  async request(method, endpoint, body, headers) {
786
- const path2 = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
787
- const url = `${this.baseUrl}${path2}`;
853
+ const path4 = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
854
+ const url = `${this.baseUrl}${path4}`;
788
855
  const reqHeaders = {
789
856
  "Authorization": `Bot ${this.token}`,
790
857
  "User-Agent": "Chameleon (https://github.com/impulsedoes/chameleon)",
@@ -796,7 +863,7 @@ var ChameleonREST = class {
796
863
  reqBody = JSON.stringify(body);
797
864
  }
798
865
  try {
799
- const response = await this.limiter.execute(method, path2, () => fetch(url, {
866
+ const response = await this.limiter.execute(method, path4, () => fetch(url, {
800
867
  method,
801
868
  headers: reqHeaders,
802
869
  ...reqBody !== void 0 ? { body: reqBody } : {}
@@ -846,6 +913,62 @@ var ChameleonREST = class {
846
913
  delete(endpoint, headers) {
847
914
  return this.request("DELETE", endpoint, void 0, headers);
848
915
  }
916
+ async requestWithFiles(method, endpoint, body, files, headers) {
917
+ const routePath = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
918
+ const url = `${this.baseUrl}${routePath}`;
919
+ const reqHeaders = {
920
+ "Authorization": `Bot ${this.token}`,
921
+ "User-Agent": "Chameleon (https://github.com/impulsedoes/chameleon)",
922
+ ...headers
923
+ };
924
+ const formData = new FormData();
925
+ const jsonPayload = {
926
+ ...body ?? {},
927
+ attachments: files.map((f, i) => f.toAttachmentJSON(i))
928
+ };
929
+ formData.append("payload_json", JSON.stringify(jsonPayload));
930
+ for (let i = 0; i < files.length; i++) {
931
+ const file = files[i];
932
+ const uint8 = file.data instanceof Uint8Array ? file.data : new Uint8Array(file.data);
933
+ const blob = new Blob([uint8], { type: file.contentType ?? "application/octet-stream" });
934
+ formData.append(`files[${i}]`, blob, file.name);
935
+ }
936
+ try {
937
+ const response = await this.limiter.execute(method, routePath, () => fetch(url, {
938
+ method,
939
+ headers: reqHeaders,
940
+ body: formData
941
+ }));
942
+ let data = null;
943
+ if (response.status !== 204) {
944
+ const text = await response.text();
945
+ if (text) {
946
+ try {
947
+ data = JSON.parse(text);
948
+ } catch {
949
+ data = text;
950
+ }
951
+ }
952
+ }
953
+ if (response.ok) {
954
+ return { ok: true, data };
955
+ }
956
+ const errData = data;
957
+ return {
958
+ ok: false,
959
+ status: response.status,
960
+ ...typeof errData?.code === "number" ? { code: errData.code } : {},
961
+ message: typeof errData?.message === "string" ? errData.message : response.statusText,
962
+ raw: data
963
+ };
964
+ } catch (error) {
965
+ return {
966
+ ok: false,
967
+ status: 0,
968
+ message: error instanceof Error ? error.message : "Unknown network error"
969
+ };
970
+ }
971
+ }
849
972
  };
850
973
 
851
974
  // src/gateway/index.ts
@@ -1215,7 +1338,7 @@ var ChameleonGateway = class {
1215
1338
  // package.json
1216
1339
  var package_default = {
1217
1340
  name: "@impulsedev/chameleon",
1218
- version: "1.7.0",
1341
+ version: "2.0.0",
1219
1342
  description: "highly optimized, memory-efficient, and fully type-safe Discord API library",
1220
1343
  main: "dist/index.js",
1221
1344
  types: "dist/index.d.ts",
@@ -1290,1541 +1413,2042 @@ var MESSAGE_FLAGS = {
1290
1413
  var CHAMELEON_VERSION = package_default.version;
1291
1414
  var CHAMELEON = package_default.name;
1292
1415
 
1293
- // src/builders/embed.ts
1294
- var Colors = {
1295
- Blue: 2003199,
1296
- Purple: 10181046,
1297
- Orange: 16744272,
1298
- Pink: 16739201,
1299
- White: 16777215,
1300
- Blurple: 5793266,
1301
- Green: 5763719,
1302
- Yellow: 16705372,
1303
- Fuchsia: 15418782,
1304
- Red: 15548997,
1305
- Black: 2303786,
1306
- Transparent: 3092790
1307
- };
1308
- var EmbedBuilder = class {
1309
- data = {};
1310
- constructor(data) {
1311
- if (data) Object.assign(this.data, data);
1312
- }
1313
- setTitle(title) {
1314
- this.data.title = title;
1315
- return this;
1316
- }
1317
- setDescription(description) {
1318
- this.data.description = description;
1319
- return this;
1320
- }
1321
- setColor(color) {
1322
- this.data.color = color;
1323
- return this;
1416
+ // src/commands/options.ts
1417
+ var opt = {
1418
+ string: (description, options) => ({
1419
+ type: "string",
1420
+ description,
1421
+ required: options?.required ?? false,
1422
+ ...options
1423
+ }),
1424
+ integer: (description, options) => ({
1425
+ type: "integer",
1426
+ description,
1427
+ required: options?.required ?? false,
1428
+ ...options
1429
+ }),
1430
+ number: (description, options) => ({
1431
+ type: "number",
1432
+ description,
1433
+ required: options?.required ?? false,
1434
+ ...options
1435
+ }),
1436
+ boolean: (description, options) => ({
1437
+ type: "boolean",
1438
+ description,
1439
+ required: options?.required ?? false
1440
+ }),
1441
+ user: (description, options) => ({
1442
+ type: "user",
1443
+ description,
1444
+ required: options?.required ?? false
1445
+ }),
1446
+ channel: (description, options) => ({
1447
+ type: "channel",
1448
+ description,
1449
+ required: options?.required ?? false
1450
+ }),
1451
+ role: (description, options) => ({
1452
+ type: "role",
1453
+ description,
1454
+ required: options?.required ?? false
1455
+ })
1456
+ };
1457
+
1458
+ // src/commands/context.ts
1459
+ var BaseInteractionContext = class {
1460
+ user;
1461
+ guild;
1462
+ channel;
1463
+ interactionId;
1464
+ interactionToken;
1465
+ _client;
1466
+ _deferred = false;
1467
+ _replied = false;
1468
+ constructor(client, raw, user, guild, channel) {
1469
+ this._client = client;
1470
+ this.interactionId = raw.id;
1471
+ this.interactionToken = raw.token;
1472
+ this.user = user;
1473
+ this.guild = guild;
1474
+ this.channel = channel;
1324
1475
  }
1325
- setURL(url) {
1326
- this.data.url = url;
1327
- return this;
1476
+ get replied() {
1477
+ return this._replied;
1328
1478
  }
1329
- setTimestamp(ts = Date.now()) {
1330
- this.data.timestamp = ts instanceof Date ? ts.getTime() : ts;
1331
- return this;
1479
+ get deferred() {
1480
+ return this._deferred;
1332
1481
  }
1333
- setFooter(text, iconUrl) {
1334
- this.data.footer = {
1335
- text,
1336
- ...iconUrl ? { iconUrl } : {}
1337
- };
1338
- return this;
1482
+ _resolvePayload(payload) {
1483
+ const data = typeof payload === "string" ? { content: payload } : { ...payload };
1484
+ if (typeof payload === "object") {
1485
+ if (payload.ephemeral) data.flags = MESSAGE_FLAGS.EPHEMERAL;
1486
+ if (payload.embeds) {
1487
+ data.embeds = payload.embeds.map((e) => {
1488
+ if (e && typeof e.toJSON === "function") {
1489
+ return e.toJSON();
1490
+ }
1491
+ return e;
1492
+ });
1493
+ }
1494
+ if (payload.components) {
1495
+ data.components = payload.components.map((c) => serializeComponent(c));
1496
+ }
1497
+ }
1498
+ return data;
1339
1499
  }
1340
- setAuthor(name, iconUrl, url) {
1341
- this.data.author = {
1342
- name,
1343
- ...iconUrl ? { iconUrl } : {},
1344
- ...url ? { url } : {}
1345
- };
1346
- return this;
1500
+ async reply(payload) {
1501
+ if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
1502
+ const data = this._resolvePayload(payload);
1503
+ await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
1504
+ type: 4 /* CHANNEL_MESSAGE_WITH_SOURCE */,
1505
+ data
1506
+ });
1507
+ this._replied = true;
1347
1508
  }
1348
- setImage(url) {
1349
- this.data.image = { url };
1350
- return this;
1509
+ async defer(options) {
1510
+ if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
1511
+ await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
1512
+ type: 5 /* DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE */,
1513
+ data: { flags: options?.ephemeral ? MESSAGE_FLAGS.EPHEMERAL : 0 }
1514
+ });
1515
+ this._deferred = true;
1351
1516
  }
1352
- setThumbnail(url) {
1353
- this.data.thumbnail = { url };
1354
- return this;
1517
+ async followUp(payload) {
1518
+ if (!this._deferred && !this._replied) throw new Error("Interaction not acknowledged.");
1519
+ const data = this._resolvePayload(payload);
1520
+ await this._client.rest.post(`/webhooks/${this._client.user?.id}/${this.interactionToken}`, data);
1355
1521
  }
1356
- addField(name, value, inline = false) {
1357
- if (!this.data.fields) this.data.fields = [];
1358
- this.data.fields.push({ name, value, inline });
1359
- return this;
1522
+ async showModal(modal) {
1523
+ if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
1524
+ const payload = modal.type === "modal" ? {
1525
+ custom_id: modal.customId,
1526
+ title: modal.title,
1527
+ components: Array.isArray(modal.fields) ? modal.fields.map((f) => ({
1528
+ type: 1 /* ACTION_ROW */,
1529
+ components: [{
1530
+ type: 4 /* TEXT_INPUT */,
1531
+ custom_id: f.id,
1532
+ style: f.type,
1533
+ label: f.label,
1534
+ required: f.required,
1535
+ min_length: f.minLength,
1536
+ max_length: f.maxLength,
1537
+ placeholder: f.placeholder,
1538
+ value: f.value
1539
+ }]
1540
+ })) : []
1541
+ } : modal;
1542
+ await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
1543
+ type: 9 /* MODAL */,
1544
+ data: payload
1545
+ });
1546
+ this._replied = true;
1360
1547
  }
1361
- addFields(...fields) {
1362
- if (!this.data.fields) this.data.fields = [];
1363
- this.data.fields.push(...fields);
1364
- return this;
1548
+ };
1549
+ var CommandContext = class extends BaseInteractionContext {
1550
+ options;
1551
+ constructor(client, rawInteraction, parsedOptions, user, guild, channel) {
1552
+ super(client, rawInteraction, user, guild, channel);
1553
+ this.options = parsedOptions;
1365
1554
  }
1366
- build() {
1367
- return this.data;
1555
+ };
1556
+
1557
+ // src/commands/command.ts
1558
+ function defineSubcommand(def) {
1559
+ return def;
1560
+ }
1561
+ function defineCommand(def) {
1562
+ if (!def.execute && (!def.subcommands || Object.keys(def.subcommands).length === 0)) {
1563
+ throw new Error(`Command ${def.name} must have an execute function or subcommands.`);
1368
1564
  }
1369
- toJSON() {
1370
- const e = this.data;
1371
- const payload = {};
1372
- if (typeof e.title === "string") payload.title = e.title;
1373
- if (typeof e.description === "string") payload.description = e.description;
1374
- if (typeof e.color === "number") payload.color = e.color;
1375
- if (typeof e.url === "string") payload.url = e.url;
1376
- if (typeof e.timestamp === "number" && !Number.isNaN(e.timestamp)) {
1377
- payload.timestamp = new Date(e.timestamp).toISOString();
1378
- }
1379
- if (e.author) {
1380
- const author = {
1381
- name: e.author.name
1382
- };
1383
- if (typeof e.author.url === "string") {
1384
- author.url = e.author.url;
1385
- }
1386
- if (typeof e.author.iconUrl === "string") {
1387
- author.icon_url = e.author.iconUrl;
1388
- }
1389
- if (typeof e.author.proxyIconUrl === "string") {
1390
- author.proxy_icon_url = e.author.proxyIconUrl;
1391
- }
1392
- payload.author = author;
1393
- }
1394
- if (e.footer) {
1395
- const footer = {
1396
- text: e.footer.text
1397
- };
1398
- if (typeof e.footer.iconUrl === "string") {
1399
- footer.icon_url = e.footer.iconUrl;
1400
- }
1401
- if (typeof e.footer.proxyIconUrl === "string") {
1402
- footer.proxy_icon_url = e.footer.proxyIconUrl;
1565
+ return def;
1566
+ }
1567
+
1568
+ // src/commands/interactions.ts
1569
+ var ModalContext = class extends BaseInteractionContext {
1570
+ customId;
1571
+ _fields = /* @__PURE__ */ new Map();
1572
+ constructor(client, raw, user, guild, channel) {
1573
+ super(client, raw, user, guild, channel);
1574
+ this.customId = raw.data?.custom_id ?? "";
1575
+ const rows = raw.data?.components ?? [];
1576
+ for (const row of rows) {
1577
+ for (const comp of row.components ?? []) {
1578
+ if (comp.custom_id && comp.value !== void 0) {
1579
+ this._fields.set(comp.custom_id, comp.value);
1580
+ }
1403
1581
  }
1404
- payload.footer = footer;
1405
- }
1406
- if (e.image?.url) {
1407
- payload.image = {
1408
- url: e.image.url
1409
- };
1410
- }
1411
- if (e.thumbnail?.url) {
1412
- payload.thumbnail = {
1413
- url: e.thumbnail.url
1414
- };
1415
1582
  }
1416
- if (Array.isArray(e.fields) && e.fields.length > 0) {
1417
- payload.fields = e.fields.map((f) => ({
1418
- name: f.name,
1419
- value: f.value,
1420
- inline: !!f.inline
1421
- }));
1422
- }
1423
- return payload;
1583
+ }
1584
+ // Get a text input value by its customId
1585
+ // values from a select menu interaction
1586
+ get values() {
1587
+ return this._values ?? [];
1588
+ }
1589
+ // Get all field values as a plain object
1590
+ get fields() {
1591
+ return Object.fromEntries(this._fields);
1424
1592
  }
1425
1593
  };
1426
1594
 
1427
- // src/builders/components.ts
1428
- function serializeEmoji(emoji) {
1429
- if (!emoji) return void 0;
1430
- return {
1431
- id: emoji.id,
1432
- name: emoji.name,
1433
- animated: emoji.animated
1434
- };
1435
- }
1436
- var ButtonBuilder = class {
1437
- data = {
1438
- type: ComponentType.BUTTON
1439
- };
1440
- setCustomId(id) {
1441
- this.data.customId = id;
1442
- return this;
1443
- }
1444
- setLabel(label) {
1445
- this.data.label = label;
1446
- return this;
1447
- }
1448
- setStyle(style) {
1449
- this.data.style = style;
1450
- return this;
1451
- }
1452
- setEmoji(emoji) {
1453
- this.data.emoji = emoji;
1454
- return this;
1455
- }
1456
- setDisabled(disabled = true) {
1457
- this.data.disabled = disabled;
1458
- return this;
1459
- }
1460
- setURL(url) {
1461
- this.data.url = url;
1462
- this.data.style = ButtonStyle.LINK;
1463
- return this;
1464
- }
1465
- build() {
1466
- return {
1467
- ...this.data
1468
- };
1469
- }
1470
- toJSON() {
1471
- return {
1472
- type: ComponentType.BUTTON,
1473
- custom_id: this.data.customId,
1474
- label: this.data.label,
1475
- style: this.data.style,
1476
- disabled: this.data.disabled,
1477
- url: this.data.url,
1478
- emoji: serializeEmoji(this.data.emoji)
1479
- };
1480
- }
1481
- };
1482
- var SelectMenuBuilder = class {
1483
- data = {
1484
- type: ComponentType.STRING_SELECT
1485
- };
1486
- setCustomId(id) {
1487
- this.data.customId = id;
1488
- return this;
1489
- }
1490
- setPlaceholder(placeholder) {
1491
- this.data.placeholder = placeholder;
1492
- return this;
1493
- }
1494
- setMinValues(min) {
1495
- this.data.minValues = min;
1496
- return this;
1497
- }
1498
- setMaxValues(max) {
1499
- this.data.maxValues = max;
1500
- return this;
1501
- }
1502
- setDisabled(disabled = true) {
1503
- this.data.disabled = disabled;
1504
- return this;
1505
- }
1506
- setType(type) {
1507
- this.data.type = type;
1508
- return this;
1509
- }
1510
- addOption(option) {
1511
- if (!this.data.options) {
1512
- this.data.options = [];
1595
+ // src/components/context.ts
1596
+ var ComponentContext = class extends BaseInteractionContext {
1597
+ customId;
1598
+ message;
1599
+ values;
1600
+ fields;
1601
+ constructor(client, raw, user, guild, channel) {
1602
+ super(client, raw, user, guild, channel);
1603
+ const data = raw.data;
1604
+ this.customId = data?.custom_id ?? "";
1605
+ if (raw.message) {
1606
+ this.message = raw.message;
1513
1607
  }
1514
- this.data.options.push(option);
1515
- return this;
1516
- }
1517
- addOptions(...options) {
1518
- if (!this.data.options) {
1519
- this.data.options = [];
1608
+ this.values = data?.values ?? [];
1609
+ const fields = {};
1610
+ if (data?.components) {
1611
+ for (const row of data.components) {
1612
+ for (const comp of row.components) {
1613
+ fields[comp.custom_id] = comp.value;
1614
+ }
1615
+ }
1520
1616
  }
1521
- this.data.options.push(...options);
1522
- return this;
1617
+ this.fields = fields;
1523
1618
  }
1524
- build() {
1525
- return {
1526
- ...this.data
1527
- };
1619
+ async deferUpdate() {
1620
+ if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
1621
+ await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
1622
+ type: 6 /* DEFERRED_UPDATE_MESSAGE */
1623
+ });
1624
+ this._deferred = true;
1528
1625
  }
1529
- toJSON() {
1530
- return {
1531
- type: this.data.type ?? ComponentType.STRING_SELECT,
1532
- custom_id: this.data.customId,
1533
- placeholder: this.data.placeholder,
1534
- min_values: this.data.minValues,
1535
- max_values: this.data.maxValues,
1536
- disabled: this.data.disabled,
1537
- options: this.data.options?.map((option) => ({
1538
- label: option.label,
1539
- value: option.value,
1540
- description: option.description,
1541
- emoji: serializeEmoji(option.emoji),
1542
- default: option.default
1543
- }))
1544
- };
1626
+ async update(payload) {
1627
+ if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
1628
+ const data = this._resolvePayload(payload);
1629
+ await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
1630
+ type: 7 /* UPDATE_MESSAGE */,
1631
+ data
1632
+ });
1633
+ this._replied = true;
1545
1634
  }
1546
1635
  };
1547
- var TextInputBuilder = class {
1548
- data = {
1549
- type: ComponentType.TEXT_INPUT
1550
- };
1551
- _minLength;
1552
- _maxLength;
1553
- _required;
1554
- _value;
1555
- setCustomId(id) {
1556
- this.data.customId = id;
1557
- return this;
1558
- }
1559
- setLabel(label) {
1560
- this.data.label = label;
1561
- return this;
1562
- }
1563
- setStyle(style) {
1564
- this.data.style = style;
1565
- return this;
1566
- }
1567
- setPlaceholder(placeholder) {
1568
- this.data.placeholder = placeholder;
1569
- return this;
1570
- }
1571
- setMinLength(length) {
1572
- this._minLength = length;
1573
- return this;
1574
- }
1575
- setMaxLength(length) {
1576
- this._maxLength = length;
1577
- return this;
1636
+
1637
+ // src/commands/manager.ts
1638
+ import * as fs from "fs";
1639
+ import * as path from "path";
1640
+ var CommandManager = class {
1641
+ _commands = /* @__PURE__ */ new Map();
1642
+ _components = [];
1643
+ _modals = [];
1644
+ _client;
1645
+ constructor(client) {
1646
+ this._client = client;
1578
1647
  }
1579
- setRequired(required = true) {
1580
- this._required = required;
1581
- return this;
1648
+ register(...commands) {
1649
+ for (const cmd of commands) {
1650
+ this._commands.set(cmd.name, cmd);
1651
+ }
1652
+ this._deployCommands(commands).catch(console.error);
1582
1653
  }
1583
- setValue(value) {
1584
- this._value = value;
1585
- return this;
1654
+ registerGuild(guildId, ...commands) {
1655
+ for (const cmd of commands) {
1656
+ this._commands.set(cmd.name, cmd);
1657
+ }
1658
+ this._deployCommands(commands, guildId).catch(console.error);
1586
1659
  }
1587
- build() {
1588
- return {
1589
- ...this.data,
1590
- minLength: this._minLength,
1591
- maxLength: this._maxLength,
1592
- required: this._required,
1593
- value: this._value
1594
- };
1660
+ registerComponent(handler) {
1661
+ this._components.push(handler);
1595
1662
  }
1596
- toJSON() {
1597
- return {
1598
- type: ComponentType.TEXT_INPUT,
1599
- custom_id: this.data.customId,
1600
- style: this.data.style,
1601
- label: this.data.label,
1602
- placeholder: this.data.placeholder,
1603
- min_length: this._minLength,
1604
- max_length: this._maxLength,
1605
- required: this._required,
1606
- value: this._value
1607
- };
1663
+ registerModal(handler) {
1664
+ this._modals.push(handler);
1608
1665
  }
1609
- };
1610
- var ActionRowBuilder = class {
1611
- data = {
1612
- type: ComponentType.ACTION_ROW,
1613
- components: []
1614
- };
1615
- addComponent(component) {
1616
- this.data.components.push(component);
1617
- return this;
1666
+ async load(directory) {
1667
+ const fullPath = path.resolve(process.cwd(), directory);
1668
+ if (!fs.existsSync(fullPath)) {
1669
+ console.error(`[Chameleon] Command directory ${directory} does not exist.`);
1670
+ return;
1671
+ }
1672
+ const files = fs.readdirSync(fullPath).filter((f) => f.endsWith(".js") || f.endsWith(".ts"));
1673
+ const commands = [];
1674
+ for (const file of files) {
1675
+ const filePath = path.join(fullPath, file);
1676
+ try {
1677
+ const module = await import(`file://${filePath}`);
1678
+ const command = module.default;
1679
+ if (command && typeof command.name === "string") {
1680
+ commands.push(command);
1681
+ }
1682
+ } catch (err) {
1683
+ console.error(`[Chameleon] Failed to load command from ${file}:`, err);
1684
+ }
1685
+ }
1686
+ if (commands.length > 0) {
1687
+ this.register(...commands);
1688
+ }
1618
1689
  }
1619
- addComponents(...components) {
1620
- for (const component of components) {
1621
- this.addComponent(component);
1690
+ async _deployCommands(commands, guildId) {
1691
+ const payload = commands.map((c) => this._transformCommand(c));
1692
+ if (this._client.user?.id) {
1693
+ const url = guildId ? `/applications/${this._client.user.id}/guilds/${guildId}/commands` : `/applications/${this._client.user.id}/commands`;
1694
+ await this._client.rest.put(url, payload);
1695
+ } else {
1696
+ this._client.on("READY", async () => {
1697
+ const url = guildId ? `/applications/${this._client.user.id}/guilds/${guildId}/commands` : `/applications/${this._client.user.id}/commands`;
1698
+ await this._client.rest.put(url, payload);
1699
+ });
1622
1700
  }
1623
- return this;
1624
1701
  }
1625
- build() {
1626
- return {
1627
- ...this.data,
1628
- components: [...this.data.components]
1702
+ _transformCommand(cmd) {
1703
+ const mapType = (t) => {
1704
+ switch (t) {
1705
+ case "string":
1706
+ return 3;
1707
+ case "integer":
1708
+ return 4;
1709
+ case "boolean":
1710
+ return 5;
1711
+ case "user":
1712
+ return 6;
1713
+ case "channel":
1714
+ return 7;
1715
+ case "role":
1716
+ return 8;
1717
+ case "number":
1718
+ return 10;
1719
+ default:
1720
+ return 3;
1721
+ }
1629
1722
  };
1630
- }
1631
- toJSON() {
1632
- return {
1633
- type: ComponentType.ACTION_ROW,
1634
- components: this.data.components?.map((component) => {
1635
- if (component && typeof component.toJSON === "function") {
1636
- return component.toJSON();
1723
+ const options = [];
1724
+ if (cmd.subcommands) {
1725
+ for (const [subName, subDef] of Object.entries(cmd.subcommands)) {
1726
+ const subOpts = [];
1727
+ if (subDef.options) {
1728
+ for (const [optName, optDefRaw] of Object.entries(subDef.options)) {
1729
+ const optDef = optDefRaw;
1730
+ subOpts.push({
1731
+ type: mapType(optDef.type),
1732
+ name: optName,
1733
+ description: optDef.description,
1734
+ required: optDef.required,
1735
+ choices: optDef.choices,
1736
+ min_value: optDef.min,
1737
+ max_value: optDef.max
1738
+ });
1739
+ }
1637
1740
  }
1638
- return component;
1639
- })
1640
- };
1641
- }
1642
- };
1643
- var ModalBuilder = class {
1644
- _title = "";
1645
- _customId = "";
1646
- _components = [];
1647
- setTitle(title) {
1648
- this._title = title;
1649
- return this;
1650
- }
1651
- setCustomId(id) {
1652
- this._customId = id;
1653
- return this;
1654
- }
1655
- addComponent(component) {
1656
- this._components.push(component);
1657
- return this;
1658
- }
1659
- addComponents(...components) {
1660
- for (const component of components) {
1661
- this.addComponent(component);
1741
+ options.push({
1742
+ type: 1 /* SUB_COMMAND */,
1743
+ name: subName,
1744
+ description: subDef.description,
1745
+ options: subOpts
1746
+ });
1747
+ }
1748
+ } else if (cmd.options) {
1749
+ for (const [optName, optDefRaw] of Object.entries(cmd.options)) {
1750
+ const optDef = optDefRaw;
1751
+ options.push({
1752
+ type: mapType(optDef.type),
1753
+ name: optName,
1754
+ description: optDef.description,
1755
+ required: optDef.required,
1756
+ choices: optDef.choices,
1757
+ min_value: optDef.min,
1758
+ max_value: optDef.max
1759
+ });
1760
+ }
1662
1761
  }
1663
- return this;
1664
- }
1665
- build() {
1666
1762
  return {
1667
- title: this._title,
1668
- custom_id: this._customId,
1669
- components: [...this._components]
1763
+ name: cmd.name,
1764
+ description: cmd.description,
1765
+ options: options.length ? options : void 0
1670
1766
  };
1671
1767
  }
1672
- toJSON() {
1673
- return {
1674
- title: this._title,
1675
- custom_id: this._customId,
1676
- components: this._components.map((component) => {
1677
- if (component && typeof component.toJSON === "function") {
1678
- return component.toJSON();
1679
- }
1680
- return component;
1681
- })
1682
- };
1768
+ async handleInteraction(raw) {
1769
+ const data = raw.data;
1770
+ if (!data) return;
1771
+ if (raw.type === 3 /* MESSAGE_COMPONENT */) return this._handleComponentInteraction(raw, data);
1772
+ if (raw.type === 5 /* MODAL_SUBMIT */) return this._handleModalInteraction(raw, data);
1773
+ if (raw.type !== 2 /* APPLICATION_COMMAND */) return;
1774
+ const name = data.name;
1775
+ if (!name) return;
1776
+ const command = this._commands.get(name);
1777
+ if (!command) return;
1778
+ const parsedOptions = {};
1779
+ let targetExecute = command.execute;
1780
+ const rawOptions = data.options || [];
1781
+ let actualOptions = rawOptions;
1782
+ if (rawOptions.length > 0 && rawOptions[0].type === 1 /* SUB_COMMAND */) {
1783
+ const subcommandName = rawOptions[0].name;
1784
+ actualOptions = rawOptions[0].options || [];
1785
+ if (command.subcommands && command.subcommands[subcommandName]) {
1786
+ targetExecute = command.subcommands[subcommandName].execute;
1787
+ }
1788
+ }
1789
+ for (const opt2 of actualOptions) {
1790
+ if (opt2.type === 6 /* USER */ && data.resolved?.users?.[opt2.value]) {
1791
+ parsedOptions[opt2.name] = resolveUser(opt2.value, this._client);
1792
+ } else if (opt2.type === 7 /* CHANNEL */ && data.resolved?.channels?.[opt2.value]) {
1793
+ parsedOptions[opt2.name] = resolveChannel(opt2.value, this._client);
1794
+ } else if (opt2.type === 8 /* ROLE */ && data.resolved?.roles?.[opt2.value]) {
1795
+ parsedOptions[opt2.name] = resolveRole(opt2.value, this._client, raw.guild_id);
1796
+ } else {
1797
+ parsedOptions[opt2.name] = opt2.value;
1798
+ }
1799
+ }
1800
+ const member = raw.member;
1801
+ const userRaw = member?.user ?? raw.user;
1802
+ const user = buildUser(userRaw);
1803
+ const ctx = new CommandContext(
1804
+ this._client,
1805
+ raw,
1806
+ parsedOptions,
1807
+ user,
1808
+ raw.guild_id ? resolveGuild(raw.guild_id, this._client) : void 0,
1809
+ raw.channel_id ? resolveChannel(raw.channel_id, this._client) : void 0
1810
+ );
1811
+ if (targetExecute) {
1812
+ try {
1813
+ await targetExecute(ctx);
1814
+ } catch (err) {
1815
+ console.error(`[Chameleon] Error executing command ${name}:`, err);
1816
+ }
1817
+ }
1683
1818
  }
1684
- };
1819
+ async _handleComponentInteraction(raw, data) {
1820
+ const customId = data.custom_id;
1821
+ const handler = this._components.find((h) => {
1822
+ if (!h.customId) return false;
1823
+ return typeof h.customId === "string" ? h.customId === customId : h.customId.test(customId);
1824
+ });
1825
+ if (!handler) return;
1826
+ const member = raw.member;
1827
+ const userRaw = member?.user ?? raw.user;
1828
+ const user = buildUser(userRaw);
1829
+ const ctx = new ComponentContext(
1830
+ this._client,
1831
+ raw,
1832
+ user,
1833
+ raw.guild_id ? resolveGuild(raw.guild_id, this._client) : void 0,
1834
+ raw.channel_id ? resolveChannel(raw.channel_id, this._client) : void 0
1835
+ );
1836
+ try {
1837
+ await handler.execute?.(ctx);
1838
+ } catch (err) {
1839
+ console.error(`[Chameleon] Error executing component ${customId}:`, err);
1840
+ }
1841
+ }
1842
+ async _handleModalInteraction(raw, data) {
1843
+ const customId = data.custom_id;
1844
+ const handler = this._modals.find(
1845
+ (h) => typeof h.customId === "string" ? h.customId === customId : h.customId.test(customId)
1846
+ );
1847
+ if (!handler) return;
1848
+ const member = raw.member;
1849
+ const userRaw = member?.user ?? raw.user;
1850
+ const user = buildUser(userRaw);
1851
+ const ctx = new ModalContext(
1852
+ this._client,
1853
+ raw,
1854
+ user,
1855
+ raw.guild_id ? resolveGuild(raw.guild_id, this._client) : void 0,
1856
+ raw.channel_id ? resolveChannel(raw.channel_id, this._client) : void 0
1857
+ );
1858
+ try {
1859
+ await handler.execute?.(ctx);
1860
+ } catch (err) {
1861
+ console.error(`[Chameleon] Error executing modal ${customId}:`, err);
1862
+ }
1863
+ }
1864
+ };
1685
1865
 
1686
- // src/builders/index.ts
1687
- function buildUser(raw) {
1688
- return {
1689
- id: raw.id,
1690
- username: raw.username,
1691
- discriminator: raw.discriminator,
1692
- globalName: raw.global_name ?? null,
1693
- avatar: raw.avatar ?? null,
1694
- bot: raw.bot ?? false,
1695
- system: raw.system ?? false,
1696
- mfaEnabled: raw.mfa_enabled ?? false,
1697
- banner: raw.banner ?? null,
1698
- accentColor: raw.accent_color ?? null,
1699
- locale: raw.locale ?? void 0,
1700
- flags: raw.flags ?? 0,
1701
- premiumType: raw.premium_type ?? 0,
1702
- publicFlags: raw.public_flags ?? 0
1703
- };
1704
- }
1705
- function buildChannel(raw, guildId) {
1706
- return {
1707
- id: raw.id,
1708
- type: raw.type,
1709
- guildId: raw.guild_id ?? guildId ?? void 0,
1710
- name: raw.name ?? null,
1711
- position: raw.position ?? 0,
1712
- parentId: raw.parent_id ?? null,
1713
- topic: raw.topic ?? null,
1714
- nsfw: raw.nsfw ?? false,
1715
- lastMessageId: raw.last_message_id ?? null,
1716
- bitrate: raw.bitrate ?? void 0,
1717
- userLimit: raw.user_limit ?? void 0,
1718
- rateLimitPerUser: raw.rate_limit_per_user ?? 0,
1719
- permissionOverwrites: raw.permission_overwrites ?? []
1720
- };
1721
- }
1722
- function buildGuild(raw) {
1723
- return {
1724
- id: raw.id,
1725
- name: raw.name,
1726
- icon: raw.icon ?? null,
1727
- splash: raw.splash ?? null,
1728
- discoverySplash: raw.discovery_splash ?? null,
1729
- ownerId: raw.owner_id,
1730
- afkChannelId: raw.afk_channel_id ?? null,
1731
- afkTimeout: raw.afk_timeout ?? 0,
1732
- verificationLevel: raw.verification_level ?? 0,
1733
- defaultMessageNotifications: raw.default_message_notifications ?? 0,
1734
- explicitContentFilter: raw.explicit_content_filter ?? 0,
1735
- features: raw.features ?? [],
1736
- mfaLevel: raw.mfa_level ?? 0,
1737
- systemChannelId: raw.system_channel_id ?? null,
1738
- systemChannelFlags: raw.system_channel_flags ?? 0,
1739
- rulesChannelId: raw.rules_channel_id ?? null,
1740
- memberCount: raw.member_count ?? 0,
1741
- vanityUrlCode: raw.vanity_url_code ?? null,
1742
- description: raw.description ?? null,
1743
- banner: raw.banner ?? null,
1744
- premiumTier: raw.premium_tier ?? 0,
1745
- premiumSubscriptionCount: raw.premium_subscription_count ?? 0,
1746
- preferredLocale: raw.preferred_locale ?? "en-US",
1747
- publicUpdatesChannelId: raw.public_updates_channel_id ?? null,
1748
- nsfwLevel: raw.nsfw_level ?? 0,
1749
- premiumProgressBarEnabled: raw.premium_progress_bar_enabled ?? false,
1750
- roles: Array.isArray(raw.roles) ? raw.roles.map((r) => buildRole(r)) : [],
1751
- emojis: raw.emojis ?? [],
1752
- applicationId: raw.application_id ?? null,
1753
- large: raw.large ?? false
1754
- };
1755
- }
1756
- function buildRole(raw) {
1757
- return {
1758
- id: raw.id,
1759
- name: raw.name,
1760
- color: raw.color ?? 0,
1761
- hoist: raw.hoist ?? false,
1762
- position: raw.position ?? 0,
1763
- permissions: raw.permissions,
1764
- managed: raw.managed ?? false,
1765
- mentionable: raw.mentionable ?? false,
1766
- icon: raw.icon ?? null,
1767
- unicodeEmoji: raw.unicode_emoji ?? null,
1768
- flags: raw.flags ?? 0
1769
- };
1866
+ // src/components/define.ts
1867
+ function resolveButtonStyle(style) {
1868
+ if (typeof style === "number") return style;
1869
+ const map = { primary: 1, secondary: 2, success: 3, danger: 4, link: 5, premium: 6 };
1870
+ return map[style] ?? 1;
1770
1871
  }
1771
- function buildMember(raw, guildId, cache) {
1772
- let userObj;
1773
- if (raw.user) {
1774
- const user = buildUser(raw.user);
1775
- cache.users.set(user.id, user);
1776
- userObj = user;
1777
- }
1778
- return {
1779
- ...userObj ? { user: userObj } : {},
1780
- nick: raw.nick ?? null,
1781
- avatar: raw.avatar ?? null,
1782
- roles: raw.roles ?? [],
1783
- joinedAt: raw.joined_at ? Date.parse(raw.joined_at) : 0,
1784
- premiumSince: raw.premium_since ? Date.parse(raw.premium_since) : null,
1785
- deaf: raw.deaf ?? false,
1786
- mute: raw.mute ?? false,
1787
- pending: raw.pending ?? false,
1788
- flags: raw.flags ?? 0,
1789
- communicationDisabledUntil: raw.communication_disabled_until ? Date.parse(raw.communication_disabled_until) : null
1790
- };
1872
+ function defineButton(def) {
1873
+ return { ...def, type: "button" };
1791
1874
  }
1792
- function buildMessage(raw, cache, oldMessage) {
1793
- const authorRaw = raw.author;
1794
- const author = authorRaw ? buildUser(authorRaw) : oldMessage?.author ?? {};
1795
- if (authorRaw && author.id) {
1796
- cache.users.set(author.id, author);
1797
- }
1798
- const msgId = raw.id ?? oldMessage?.id;
1799
- const channelId = raw.channel_id ?? oldMessage?.channelId;
1800
- const guildId = raw.guild_id ? raw.guild_id : oldMessage?.guildId;
1801
- const msg = {
1802
- id: msgId,
1803
- channelId,
1804
- author,
1805
- ...guildId ? { guildId } : {},
1806
- url: `https://discord.com/channels/${guildId ?? "@me"}/${channelId}/${msgId}`,
1807
- content: raw.content ?? oldMessage?.content ?? "",
1808
- timestamp: raw.timestamp ? Date.parse(raw.timestamp) : oldMessage?.timestamp ?? Date.now(),
1809
- editedTimestamp: raw.edited_timestamp ? Date.parse(raw.edited_timestamp) : oldMessage?.editedTimestamp ?? null,
1810
- tts: raw.tts ?? oldMessage?.tts ?? false,
1811
- mentionEveryone: raw.mention_everyone ?? oldMessage?.mentionEveryone ?? false,
1812
- mentions: raw.mentions ? raw.mentions.map((m) => buildUser(m)) : oldMessage?.mentions ?? [],
1813
- mentionRoles: raw.mention_roles ?? oldMessage?.mentionRoles ?? [],
1814
- attachments: raw.attachments ?? oldMessage?.attachments ?? [],
1815
- embeds: raw.embeds ?? oldMessage?.embeds ?? [],
1816
- pinned: raw.pinned ?? oldMessage?.pinned ?? false,
1817
- type: raw.type ?? oldMessage?.type ?? 0
1818
- };
1819
- return msg;
1875
+ function defineStringSelect(def) {
1876
+ return { ...def, type: "string_select" };
1820
1877
  }
1821
- function resolveChannel(channelId, cache) {
1822
- return cache.channels.get(channelId) ?? { id: channelId };
1878
+ function defineUserSelect(def) {
1879
+ return { ...def, type: "user_select" };
1823
1880
  }
1824
- function resolveGuild(guildId, cache) {
1825
- return cache.guilds.get(guildId) ?? { id: guildId };
1881
+ function defineRoleSelect(def) {
1882
+ return { ...def, type: "role_select" };
1826
1883
  }
1827
- function resolveUser(userId, cache) {
1828
- return cache.users.get(userId) ?? { id: userId };
1884
+ function defineChannelSelect(def) {
1885
+ return { ...def, type: "channel_select" };
1829
1886
  }
1830
- function resolveRole(roleId, cache) {
1831
- return cache.roles.get(roleId) ?? { id: roleId };
1887
+ function defineMentionableSelect(def) {
1888
+ return { ...def, type: "mentionable_select" };
1832
1889
  }
1833
-
1834
- // src/commands/options.ts
1835
- var opt = {
1836
- string: (description, options) => ({
1837
- type: "string",
1838
- description,
1839
- required: options?.required ?? false,
1840
- ...options
1841
- }),
1842
- integer: (description, options) => ({
1843
- type: "integer",
1844
- description,
1845
- required: options?.required ?? false,
1890
+ var field = {
1891
+ short: (id, label, options) => ({
1892
+ id,
1893
+ type: 1 /* SHORT */,
1894
+ label,
1895
+ required: options?.required ?? true,
1846
1896
  ...options
1847
1897
  }),
1848
- number: (description, options) => ({
1849
- type: "number",
1850
- description,
1851
- required: options?.required ?? false,
1898
+ paragraph: (id, label, options) => ({
1899
+ id,
1900
+ type: 2 /* PARAGRAPH */,
1901
+ label,
1902
+ required: options?.required ?? true,
1852
1903
  ...options
1853
- }),
1854
- boolean: (description, options) => ({
1855
- type: "boolean",
1856
- description,
1857
- required: options?.required ?? false
1858
- }),
1859
- user: (description, options) => ({
1860
- type: "user",
1861
- description,
1862
- required: options?.required ?? false
1863
- }),
1864
- channel: (description, options) => ({
1865
- type: "channel",
1866
- description,
1867
- required: options?.required ?? false
1868
- }),
1869
- role: (description, options) => ({
1870
- type: "role",
1871
- description,
1872
- required: options?.required ?? false
1873
1904
  })
1874
1905
  };
1906
+ function defineModal(def) {
1907
+ return { ...def, type: "modal" };
1908
+ }
1875
1909
 
1876
- // src/commands/context.ts
1877
- var CommandContext = class {
1878
- options;
1879
- user;
1880
- guild;
1881
- channel;
1882
- interactionId;
1883
- interactionToken;
1884
- _client;
1885
- _deferred = false;
1886
- _replied = false;
1887
- constructor(client, rawInteraction, parsedOptions, user, guild, channel) {
1888
- this._client = client;
1889
- this.interactionId = rawInteraction.id;
1890
- this.interactionToken = rawInteraction.token;
1891
- this.options = parsedOptions;
1892
- this.user = user;
1893
- this.guild = guild;
1894
- this.channel = channel;
1895
- }
1896
- get replied() {
1897
- return this._replied;
1898
- }
1899
- get deferred() {
1900
- return this._deferred;
1910
+ // src/components/actionRow.ts
1911
+ var ActionRow = {
1912
+ of: (...components) => {
1913
+ return {
1914
+ type: 1 /* ACTION_ROW */,
1915
+ components: components.map((c) => {
1916
+ if ("type" in c && c.type === "button") {
1917
+ const btn = c;
1918
+ return {
1919
+ type: 2 /* BUTTON */,
1920
+ custom_id: btn.customId,
1921
+ url: btn.url,
1922
+ label: btn.label,
1923
+ style: resolveButtonStyle(btn.style),
1924
+ disabled: btn.disabled,
1925
+ emoji: btn.emoji,
1926
+ sku_id: btn.skuId
1927
+ };
1928
+ }
1929
+ if ("type" in c && c.type === "string_select") {
1930
+ const sel = c;
1931
+ return {
1932
+ type: 3 /* STRING_SELECT */,
1933
+ custom_id: sel.customId,
1934
+ options: sel.options,
1935
+ placeholder: sel.placeholder,
1936
+ min_values: sel.minValues,
1937
+ max_values: sel.maxValues,
1938
+ disabled: sel.disabled
1939
+ };
1940
+ }
1941
+ if ("type" in c && c.type === "user_select") {
1942
+ const sel = c;
1943
+ return { type: 5 /* USER_SELECT */, custom_id: sel.customId, placeholder: sel.placeholder, min_values: sel.minValues, max_values: sel.maxValues, disabled: sel.disabled };
1944
+ }
1945
+ if ("type" in c && c.type === "role_select") {
1946
+ const sel = c;
1947
+ return { type: 6 /* ROLE_SELECT */, custom_id: sel.customId, placeholder: sel.placeholder, min_values: sel.minValues, max_values: sel.maxValues, disabled: sel.disabled };
1948
+ }
1949
+ if ("type" in c && c.type === "mentionable_select") {
1950
+ const sel = c;
1951
+ return { type: 7 /* MENTIONABLE_SELECT */, custom_id: sel.customId, placeholder: sel.placeholder, min_values: sel.minValues, max_values: sel.maxValues, disabled: sel.disabled };
1952
+ }
1953
+ if ("type" in c && c.type === "channel_select") {
1954
+ const sel = c;
1955
+ return { type: 8 /* CHANNEL_SELECT */, custom_id: sel.customId, channel_types: sel.channelTypes, placeholder: sel.placeholder, min_values: sel.minValues, max_values: sel.maxValues, disabled: sel.disabled };
1956
+ }
1957
+ if ("type" in c && (c.type === 1 /* SHORT */ || c.type === 2 /* PARAGRAPH */)) {
1958
+ const field2 = c;
1959
+ return {
1960
+ type: 4 /* TEXT_INPUT */,
1961
+ custom_id: field2.id,
1962
+ style: field2.type,
1963
+ label: field2.label,
1964
+ required: field2.required,
1965
+ min_length: field2.minLength,
1966
+ max_length: field2.maxLength,
1967
+ placeholder: field2.placeholder,
1968
+ value: field2.value
1969
+ };
1970
+ }
1971
+ return c;
1972
+ }).map((obj) => {
1973
+ const clean = {};
1974
+ for (const [k, v] of Object.entries(obj)) {
1975
+ if (v !== void 0) clean[k] = v;
1976
+ }
1977
+ return clean;
1978
+ })
1979
+ };
1901
1980
  }
1902
- async reply(payload) {
1903
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
1904
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
1905
- if (typeof payload === "object" && payload.ephemeral) data.flags = 64;
1906
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
1907
- type: 4 /* CHANNEL_MESSAGE_WITH_SOURCE */,
1908
- data
1909
- });
1910
- this._replied = true;
1981
+ };
1982
+
1983
+ // src/components/manager.ts
1984
+ var ComponentManager = class {
1985
+ constructor(client) {
1986
+ this.client = client;
1911
1987
  }
1912
- async defer(options) {
1913
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
1914
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
1915
- type: 5 /* DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE */,
1916
- data: {
1917
- flags: options?.ephemeral ? 64 : 0
1988
+ client;
1989
+ handlers = /* @__PURE__ */ new Map();
1990
+ register(...components) {
1991
+ for (const comp of components) {
1992
+ if (comp.customId && typeof comp.customId === "string") {
1993
+ this.handlers.set(comp.customId, comp);
1918
1994
  }
1919
- });
1920
- this._deferred = true;
1921
- }
1922
- async followUp(payload) {
1923
- if (!this._deferred && !this._replied) throw new Error("Interaction not acknowledged. Use reply or defer first.");
1924
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
1925
- if (typeof payload === "object" && payload.ephemeral) data.flags = 64;
1926
- await this._client.rest.post(`/webhooks/${this._client.user?.id}/${this.interactionToken}`, data);
1995
+ }
1927
1996
  }
1928
- async showModal(modal) {
1929
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
1930
- const payload = modal.type === "modal" ? {
1931
- custom_id: modal.customId,
1932
- title: modal.title,
1933
- components: modal.fields.map((f) => ({
1934
- type: 1 /* ACTION_ROW */,
1935
- components: [{
1936
- type: 4 /* TEXT_INPUT */,
1937
- custom_id: f.id,
1938
- style: f.type,
1939
- // 1 short, 2 paragraph
1940
- label: f.label,
1941
- required: f.required,
1942
- min_length: f.minLength,
1943
- max_length: f.maxLength,
1944
- placeholder: f.placeholder,
1945
- value: f.value
1946
- }]
1947
- }))
1948
- } : modal;
1949
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
1950
- type: 9 /* MODAL */,
1951
- data: payload
1952
- });
1953
- this._replied = true;
1997
+ async handleInteraction(raw) {
1998
+ const data = raw.data;
1999
+ if (!data) return;
2000
+ const customId = data.custom_id;
2001
+ if (!customId) return;
2002
+ const handler = this.handlers.get(customId);
2003
+ if (!handler || !handler.execute) return;
2004
+ const userRaw = raw.member?.user ?? raw.user;
2005
+ const user = buildUser(userRaw);
2006
+ let guild;
2007
+ if (raw.guild_id) {
2008
+ guild = this.client.cache.guilds.get(raw.guild_id) ?? { id: raw.guild_id };
2009
+ }
2010
+ let channel;
2011
+ if (raw.channel_id) {
2012
+ channel = resolveChannel(raw.channel_id, this.client) ?? { id: raw.channel_id };
2013
+ }
2014
+ const resolved = data.resolved;
2015
+ if (resolved?.members && resolved?.users && raw.guild_id) {
2016
+ for (const [id] of Object.entries(resolved.members)) {
2017
+ const userData = resolved.users[id];
2018
+ if (userData) {
2019
+ const u = buildUser(userData);
2020
+ this.client.cache.users.set(u.id, u);
2021
+ }
2022
+ }
2023
+ }
2024
+ const ctx = new ComponentContext(this.client, raw, user, guild, channel);
2025
+ if (handler.type === "user_select" && resolved?.users) {
2026
+ ctx.values = ctx.values.map((id) => {
2027
+ const uData = resolved.users[id];
2028
+ return uData ? buildUser(uData) : { id };
2029
+ });
2030
+ } else if (handler.type === "channel_select" && resolved?.channels) {
2031
+ ctx.values = ctx.values.map((id) => {
2032
+ const cData = resolved.channels[id];
2033
+ return cData ? buildChannel(cData, raw.guild_id) : { id };
2034
+ });
2035
+ }
2036
+ try {
2037
+ await handler.execute(ctx);
2038
+ } catch (err) {
2039
+ console.error(`[COMPONENTS] Error executing component ${customId}:`, err);
2040
+ }
1954
2041
  }
1955
2042
  };
1956
2043
 
1957
- // src/commands/command.ts
1958
- function defineSubcommand(def) {
1959
- return def;
1960
- }
1961
- function defineCommand(def) {
1962
- if (!def.execute && (!def.subcommands || Object.keys(def.subcommands).length === 0)) {
1963
- throw new Error(`Command ${def.name} must have an execute function or subcommands.`);
1964
- }
1965
- return def;
1966
- }
1967
-
1968
- // src/commands/interactions.ts
1969
- var ComponentContext = class {
1970
- customId;
1971
- user;
1972
- guild;
1973
- channel;
1974
- message;
1975
- interactionId;
1976
- interactionToken;
1977
- _client;
1978
- _deferred = false;
1979
- _replied = false;
1980
- constructor(client, raw, user, guild, channel) {
1981
- this._client = client;
1982
- this.interactionId = raw.id;
1983
- this.interactionToken = raw.token;
1984
- this.customId = raw.data?.custom_id ?? "";
1985
- this.message = raw.message;
1986
- this.user = user;
1987
- this.guild = guild;
1988
- this.channel = channel;
1989
- }
1990
- get replied() {
1991
- return this._replied;
2044
+ // src/managers/base.ts
2045
+ var BaseManager = class {
2046
+ constructor(rest, store) {
2047
+ this.rest = rest;
2048
+ this.store = store;
1992
2049
  }
1993
- get deferred() {
1994
- return this._deferred;
2050
+ rest;
2051
+ store;
2052
+ async fetch(id, force = false) {
2053
+ if (!force) {
2054
+ const tongue2 = this.store[this.storeKey];
2055
+ const cached = tongue2.get(id);
2056
+ if (cached) return { ok: true, data: cached };
2057
+ }
2058
+ const result = await this.rest.get(this.endpoint(id));
2059
+ if (!result.ok) return result;
2060
+ const entity = this.build(result.data);
2061
+ const tongue = this.store[this.storeKey];
2062
+ tongue.set(id, entity);
2063
+ return { ok: true, data: entity };
1995
2064
  }
1996
- /** Values from a select menu interaction */
1997
- get values() {
1998
- return this._values ?? [];
2065
+ };
2066
+
2067
+ // src/managers/user.ts
2068
+ var UserManager = class extends BaseManager {
2069
+ storeKey = "users";
2070
+ endpoint(id) {
2071
+ return `/users/${id}`;
1999
2072
  }
2000
- async reply(payload) {
2001
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2002
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
2003
- if (typeof payload === "object" && payload.ephemeral) data.flags = 64;
2004
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2005
- type: 4 /* CHANNEL_MESSAGE_WITH_SOURCE */,
2006
- data
2007
- });
2008
- this._replied = true;
2073
+ build = buildUser;
2074
+ async createDM(userId) {
2075
+ const result = await this.rest.post("/users/@me/channels", { recipient_id: userId });
2076
+ if (!result.ok) return result;
2077
+ return { ok: true, data: (await import("./builders-WHD6LQWX.js")).buildChannel(result.data) };
2009
2078
  }
2010
- async deferUpdate() {
2011
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2012
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2013
- type: 6 /* DEFERRED_UPDATE_MESSAGE */
2014
- });
2015
- this._deferred = true;
2079
+ async editCurrent(payload) {
2080
+ const result = await this.rest.patch("/users/@me", toSnakeCase(payload));
2081
+ if (!result.ok) return result;
2082
+ const user = this.build(result.data);
2083
+ this.store.users.set(user.id, user);
2084
+ return { ok: true, data: user };
2016
2085
  }
2017
- async update(payload) {
2018
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2019
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
2020
- if (typeof payload === "object" && payload.ephemeral) data.flags = 64;
2021
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2022
- type: 7 /* UPDATE_MESSAGE */,
2023
- data
2024
- });
2025
- this._replied = true;
2086
+ };
2087
+
2088
+ // src/managers/role.ts
2089
+ var RoleManager = class {
2090
+ constructor(rest, store, guildId) {
2091
+ this.rest = rest;
2092
+ this.store = store;
2093
+ this.guildId = guildId;
2026
2094
  }
2027
- async followUp(payload) {
2028
- if (!this._deferred && !this._replied) throw new Error("Interaction not acknowledged.");
2029
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
2030
- if (typeof payload === "object" && payload.ephemeral) data.flags = 64;
2031
- await this._client.rest.post(`/webhooks/${this._client.user?.id}/${this.interactionToken}`, data);
2095
+ rest;
2096
+ store;
2097
+ guildId;
2098
+ async fetch(roleId, force = false) {
2099
+ if (!force) {
2100
+ const cached = this.store.roles.get(roleId);
2101
+ if (cached) return { ok: true, data: cached };
2102
+ }
2103
+ const result = await this.rest.get(`/guilds/${this.guildId}/roles`);
2104
+ if (!result.ok) return result;
2105
+ const roles = result.data.map((raw) => buildRole(raw));
2106
+ for (const r of roles) {
2107
+ this.store.roles.set(r.id, r);
2108
+ }
2109
+ const target = roles.find((r) => r.id === roleId);
2110
+ if (target) return { ok: true, data: target };
2111
+ return { ok: false, status: 404, message: "Role not found" };
2032
2112
  }
2033
- };
2034
- var ModalContext = class {
2035
- customId;
2036
- user;
2037
- guild;
2038
- channel;
2039
- interactionId;
2040
- interactionToken;
2041
- _fields = /* @__PURE__ */ new Map();
2042
- _client;
2043
- _replied = false;
2044
- _deferred = false;
2045
- constructor(client, raw, user, guild, channel) {
2046
- this._client = client;
2047
- this.interactionId = raw.id;
2048
- this.interactionToken = raw.token;
2049
- this.customId = raw.data?.custom_id ?? "";
2050
- this.user = user;
2051
- this.guild = guild;
2052
- this.channel = channel;
2053
- const rows = raw.data?.components ?? [];
2054
- for (const row of rows) {
2055
- for (const comp of row.components ?? []) {
2056
- if (comp.custom_id && comp.value !== void 0) {
2057
- this._fields.set(comp.custom_id, comp.value);
2058
- }
2059
- }
2113
+ async list() {
2114
+ const result = await this.rest.get(`/guilds/${this.guildId}/roles`);
2115
+ if (!result.ok) return result;
2116
+ const roles = result.data.map((raw) => buildRole(raw));
2117
+ for (const r of roles) {
2118
+ this.store.roles.set(r.id, r);
2060
2119
  }
2120
+ return { ok: true, data: roles };
2061
2121
  }
2062
- get replied() {
2063
- return this._replied;
2122
+ async create(payload, reason) {
2123
+ const headers = {};
2124
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2125
+ const result = await this.rest.post(`/guilds/${this.guildId}/roles`, toSnakeCase(payload), headers);
2126
+ if (!result.ok) return result;
2127
+ const role = buildRole(result.data);
2128
+ this.store.roles.set(role.id, role);
2129
+ return { ok: true, data: role };
2064
2130
  }
2065
- get deferred() {
2066
- return this._deferred;
2131
+ async edit(roleId, payload, reason) {
2132
+ const headers = {};
2133
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2134
+ const result = await this.rest.patch(`/guilds/${this.guildId}/roles/${roleId}`, toSnakeCase(payload), headers);
2135
+ if (!result.ok) return result;
2136
+ const role = buildRole(result.data);
2137
+ this.store.roles.set(role.id, role);
2138
+ return { ok: true, data: role };
2067
2139
  }
2068
- /** Get a text input value by its customId */
2069
- getField(customId) {
2070
- return this._fields.get(customId);
2140
+ async delete(roleId, reason) {
2141
+ const headers = {};
2142
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2143
+ const result = await this.rest.delete(`/guilds/${this.guildId}/roles/${roleId}`, headers);
2144
+ if (result.ok) this.store.roles.delete(roleId);
2145
+ return result;
2071
2146
  }
2072
- /** Get all field values as a plain object */
2073
- get fields() {
2074
- return Object.fromEntries(this._fields);
2147
+ };
2148
+
2149
+ // src/managers/member.ts
2150
+ var MemberManager = class {
2151
+ constructor(rest, store, guildId) {
2152
+ this.rest = rest;
2153
+ this.store = store;
2154
+ this.guildId = guildId;
2075
2155
  }
2076
- async reply(payload) {
2077
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2078
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
2079
- if (typeof payload === "object" && payload.ephemeral) data.flags = 64;
2080
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2081
- type: 4 /* CHANNEL_MESSAGE_WITH_SOURCE */,
2082
- data
2156
+ rest;
2157
+ store;
2158
+ guildId;
2159
+ async fetch(userId, force = false) {
2160
+ const cacheKey = TongueStore.memberKey(this.guildId, userId);
2161
+ if (!force) {
2162
+ const cached = this.store.members.get(cacheKey);
2163
+ if (cached) return { ok: true, data: cached };
2164
+ }
2165
+ const result = await this.rest.get(`/guilds/${this.guildId}/members/${userId}`);
2166
+ if (!result.ok) return result;
2167
+ const member = buildMember(result.data, this.guildId, this.store);
2168
+ this.store.members.set(cacheKey, member);
2169
+ return { ok: true, data: member };
2170
+ }
2171
+ async edit(userId, payload, reason) {
2172
+ const headers = {};
2173
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2174
+ const result = await this.rest.patch(`/guilds/${this.guildId}/members/${userId}`, toSnakeCase(payload), headers);
2175
+ if (!result.ok) return result;
2176
+ const cacheKey = TongueStore.memberKey(this.guildId, userId);
2177
+ const member = buildMember(result.data, this.guildId, this.store);
2178
+ this.store.members.set(cacheKey, member);
2179
+ return { ok: true, data: member };
2180
+ }
2181
+ async list(options) {
2182
+ let url = `/guilds/${this.guildId}/members`;
2183
+ if (options) {
2184
+ const params = new URLSearchParams();
2185
+ if (options.limit) params.append("limit", options.limit.toString());
2186
+ if (options.after) params.append("after", options.after);
2187
+ const qs = params.toString();
2188
+ if (qs) url += `?${qs}`;
2189
+ }
2190
+ const result = await this.rest.get(url);
2191
+ if (!result.ok) return result;
2192
+ const members = result.data.map((m) => {
2193
+ const member = buildMember(m, this.guildId, this.store);
2194
+ if (member.user) {
2195
+ this.store.members.set(TongueStore.memberKey(this.guildId, member.user.id), member);
2196
+ }
2197
+ return member;
2083
2198
  });
2084
- this._replied = true;
2199
+ return { ok: true, data: members };
2085
2200
  }
2086
- async defer(options) {
2087
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2088
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2089
- type: 5 /* DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE */,
2090
- data: { flags: options?.ephemeral ? 64 : 0 }
2201
+ async search(query, limit) {
2202
+ const params = new URLSearchParams({ query });
2203
+ if (limit) params.append("limit", limit.toString());
2204
+ const result = await this.rest.get(`/guilds/${this.guildId}/members/search?${params.toString()}`);
2205
+ if (!result.ok) return result;
2206
+ const members = result.data.map((m) => {
2207
+ const member = buildMember(m, this.guildId, this.store);
2208
+ if (member.user) {
2209
+ this.store.members.set(TongueStore.memberKey(this.guildId, member.user.id), member);
2210
+ }
2211
+ return member;
2091
2212
  });
2092
- this._deferred = true;
2213
+ return { ok: true, data: members };
2093
2214
  }
2094
- async followUp(payload) {
2095
- if (!this._deferred && !this._replied) throw new Error("Interaction not acknowledged.");
2096
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
2097
- if (typeof payload === "object" && payload.ephemeral) data.flags = 64;
2098
- await this._client.rest.post(`/webhooks/${this._client.user?.id}/${this.interactionToken}`, data);
2215
+ async addRole(userId, roleId, reason) {
2216
+ const headers = {};
2217
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2218
+ const result = await this.rest.put(`/guilds/${this.guildId}/members/${userId}/roles/${roleId}`, void 0, headers);
2219
+ return result;
2220
+ }
2221
+ async removeRole(userId, roleId, reason) {
2222
+ const headers = {};
2223
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2224
+ const result = await this.rest.delete(`/guilds/${this.guildId}/members/${userId}/roles/${roleId}`, headers);
2225
+ return result;
2226
+ }
2227
+ async timeout(userId, until, reason) {
2228
+ const isoString = until ? until instanceof Date ? until.toISOString() : new Date(until).toISOString() : null;
2229
+ return this.edit(userId, { communicationDisabledUntil: isoString }, reason);
2099
2230
  }
2100
2231
  };
2101
2232
 
2102
- // src/commands/manager.ts
2103
- import * as fs from "fs";
2104
- import * as path from "path";
2105
- var CommandManager = class {
2106
- _commands = /* @__PURE__ */ new Map();
2107
- _components = [];
2108
- _modals = [];
2109
- _client;
2110
- constructor(client) {
2111
- this._client = client;
2233
+ // src/managers/guild.ts
2234
+ var GuildManager = class extends BaseManager {
2235
+ storeKey = "guilds";
2236
+ endpoint(id) {
2237
+ return `/guilds/${id}`;
2112
2238
  }
2113
- register(...commands) {
2114
- for (const cmd of commands) {
2115
- this._commands.set(cmd.name, cmd);
2239
+ build = buildGuild;
2240
+ roles(guildId) {
2241
+ return new RoleManager(this.rest, this.store, guildId);
2242
+ }
2243
+ members(guildId) {
2244
+ return new MemberManager(this.rest, this.store, guildId);
2245
+ }
2246
+ async fetchChannels(guildId) {
2247
+ const result = await this.rest.get(`/guilds/${guildId}/channels`);
2248
+ if (!result.ok) return result;
2249
+ const channels = result.data.map((raw) => buildChannel(raw, guildId));
2250
+ for (const c of channels) {
2251
+ this.store.channels.set(c.id, c);
2116
2252
  }
2117
- this._deployCommands(commands).catch(console.error);
2253
+ return { ok: true, data: channels };
2118
2254
  }
2119
- registerComponent(handler) {
2120
- this._components.push(handler);
2255
+ async ban(guildId, userId, options) {
2256
+ const payload = {};
2257
+ if (options?.deleteMessageSeconds !== void 0) payload.delete_message_seconds = options.deleteMessageSeconds;
2258
+ const headers = {};
2259
+ if (options?.reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(options.reason);
2260
+ const result = await this.rest.put(`/guilds/${guildId}/bans/${userId}`, payload, headers);
2261
+ return result;
2121
2262
  }
2122
- registerModal(handler) {
2123
- this._modals.push(handler);
2263
+ async unban(guildId, userId, reason) {
2264
+ const headers = {};
2265
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2266
+ const result = await this.rest.delete(`/guilds/${guildId}/bans/${userId}`, headers);
2267
+ return result;
2124
2268
  }
2125
- async load(directory) {
2126
- const fullPath = path.resolve(process.cwd(), directory);
2127
- if (!fs.existsSync(fullPath)) {
2128
- console.error(`[Chameleon] Command directory ${directory} does not exist.`);
2129
- return;
2269
+ async kick(guildId, userId, reason) {
2270
+ const headers = {};
2271
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2272
+ const result = await this.rest.delete(`/guilds/${guildId}/members/${userId}`, headers);
2273
+ if (result.ok) {
2274
+ this.store.members.delete(TongueStore.memberKey(guildId, userId));
2130
2275
  }
2131
- const files = fs.readdirSync(fullPath).filter((f) => f.endsWith(".js") || f.endsWith(".ts"));
2132
- const commands = [];
2133
- for (const file of files) {
2134
- const filePath = path.join(fullPath, file);
2135
- try {
2136
- const module = await import(`file://${filePath}`);
2137
- const command = module.default;
2138
- if (command && typeof command.name === "string") {
2139
- commands.push(command);
2140
- }
2141
- } catch (err) {
2142
- console.error(`[Chameleon] Failed to load command from ${file}:`, err);
2143
- }
2276
+ return result;
2277
+ }
2278
+ async edit(guildId, payload, reason) {
2279
+ const headers = {};
2280
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2281
+ const result = await this.rest.patch(this.endpoint(guildId), toSnakeCase(payload), headers);
2282
+ if (!result.ok) return result;
2283
+ const entity = this.build(result.data);
2284
+ this.store.guilds.set(entity.id, entity);
2285
+ return { ok: true, data: entity };
2286
+ }
2287
+ async delete(guildId) {
2288
+ const result = await this.rest.delete(this.endpoint(guildId));
2289
+ if (result.ok) this.store.guilds.delete(guildId);
2290
+ return result;
2291
+ }
2292
+ async listEmojis(guildId) {
2293
+ const result = await this.rest.get(`/guilds/${guildId}/emojis`);
2294
+ if (!result.ok) return result;
2295
+ const emojis = result.data.map((e) => {
2296
+ const emoji = buildEmoji(e);
2297
+ this.store.emojis.set(emoji.id, emoji);
2298
+ return emoji;
2299
+ });
2300
+ return { ok: true, data: emojis };
2301
+ }
2302
+ async fetchEmoji(guildId, emojiId) {
2303
+ const cached = this.store.emojis.get(emojiId);
2304
+ if (cached) return { ok: true, data: cached };
2305
+ const result = await this.rest.get(`/guilds/${guildId}/emojis/${emojiId}`);
2306
+ if (!result.ok) return result;
2307
+ const emoji = buildEmoji(result.data);
2308
+ this.store.emojis.set(emoji.id, emoji);
2309
+ return { ok: true, data: emoji };
2310
+ }
2311
+ async createEmoji(guildId, payload, reason) {
2312
+ const headers = {};
2313
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2314
+ const result = await this.rest.post(`/guilds/${guildId}/emojis`, toSnakeCase(payload), headers);
2315
+ if (!result.ok) return result;
2316
+ const emoji = buildEmoji(result.data);
2317
+ this.store.emojis.set(emoji.id, emoji);
2318
+ return { ok: true, data: emoji };
2319
+ }
2320
+ async editEmoji(guildId, emojiId, payload, reason) {
2321
+ const headers = {};
2322
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2323
+ const result = await this.rest.patch(`/guilds/${guildId}/emojis/${emojiId}`, toSnakeCase(payload), headers);
2324
+ if (!result.ok) return result;
2325
+ const emoji = buildEmoji(result.data);
2326
+ this.store.emojis.set(emoji.id, emoji);
2327
+ return { ok: true, data: emoji };
2328
+ }
2329
+ async deleteEmoji(guildId, emojiId, reason) {
2330
+ const headers = {};
2331
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2332
+ const result = await this.rest.delete(`/guilds/${guildId}/emojis/${emojiId}`, headers);
2333
+ if (result.ok) this.store.emojis.delete(emojiId);
2334
+ return result;
2335
+ }
2336
+ async listStickers(guildId) {
2337
+ const result = await this.rest.get(`/guilds/${guildId}/stickers`);
2338
+ if (!result.ok) return result;
2339
+ const stickers = result.data.map((s) => {
2340
+ const sticker = buildSticker(s);
2341
+ this.store.stickers.set(sticker.id, sticker);
2342
+ return sticker;
2343
+ });
2344
+ return { ok: true, data: stickers };
2345
+ }
2346
+ async fetchSticker(guildId, stickerId) {
2347
+ const cached = this.store.stickers.get(stickerId);
2348
+ if (cached) return { ok: true, data: cached };
2349
+ const result = await this.rest.get(`/guilds/${guildId}/stickers/${stickerId}`);
2350
+ if (!result.ok) return result;
2351
+ const sticker = buildSticker(result.data);
2352
+ this.store.stickers.set(sticker.id, sticker);
2353
+ return { ok: true, data: sticker };
2354
+ }
2355
+ async listBans(guildId, options) {
2356
+ let url = `/guilds/${guildId}/bans`;
2357
+ if (options) {
2358
+ const params = new URLSearchParams();
2359
+ if (options.limit) params.append("limit", options.limit.toString());
2360
+ if (options.before) params.append("before", options.before);
2361
+ if (options.after) params.append("after", options.after);
2362
+ const qs = params.toString();
2363
+ if (qs) url += `?${qs}`;
2144
2364
  }
2145
- if (commands.length > 0) {
2146
- this.register(...commands);
2365
+ const result = await this.rest.get(url);
2366
+ if (!result.ok) return result;
2367
+ const bans = result.data.map((b) => ({
2368
+ reason: b.reason ?? null,
2369
+ user: buildUser(b.user)
2370
+ }));
2371
+ return { ok: true, data: bans };
2372
+ }
2373
+ async fetchBan(guildId, userId) {
2374
+ const result = await this.rest.get(`/guilds/${guildId}/bans/${userId}`);
2375
+ if (!result.ok) return result;
2376
+ const b = result.data;
2377
+ return {
2378
+ ok: true,
2379
+ data: { reason: b.reason ?? null, user: buildUser(b.user) }
2380
+ };
2381
+ }
2382
+ async getInvites(guildId) {
2383
+ const result = await this.rest.get(`/guilds/${guildId}/invites`);
2384
+ if (!result.ok) return result;
2385
+ const invites = result.data.map((i) => buildInvite(i));
2386
+ return { ok: true, data: invites };
2387
+ }
2388
+ async getVanityURL(guildId) {
2389
+ const result = await this.rest.get(`/guilds/${guildId}/vanity-url`);
2390
+ if (!result.ok) return result;
2391
+ const data = result.data;
2392
+ return { ok: true, data: { code: data.code ?? null, uses: data.uses ?? 0 } };
2393
+ }
2394
+ async getPruneCount(guildId, options) {
2395
+ let url = `/guilds/${guildId}/prune`;
2396
+ if (options) {
2397
+ const params = new URLSearchParams();
2398
+ if (options.days) params.append("days", options.days.toString());
2399
+ if (options.includeRoles) params.append("include_roles", options.includeRoles.join(","));
2400
+ const qs = params.toString();
2401
+ if (qs) url += `?${qs}`;
2147
2402
  }
2403
+ const result = await this.rest.get(url);
2404
+ if (!result.ok) return result;
2405
+ return { ok: true, data: result.data.pruned ?? 0 };
2148
2406
  }
2149
- async _deployCommands(commands) {
2150
- const payload = commands.map((c) => this._transformCommand(c));
2151
- if (this._client.user?.id) {
2152
- await this._client.rest.put(`/applications/${this._client.user.id}/commands`, payload);
2407
+ async beginPrune(guildId, options, reason) {
2408
+ const headers = {};
2409
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2410
+ const result = await this.rest.post(`/guilds/${guildId}/prune`, toSnakeCase(options ?? {}), headers);
2411
+ if (!result.ok) return result;
2412
+ return { ok: true, data: result.data.pruned ?? null };
2413
+ }
2414
+ async fetchAuditLog(guildId, options) {
2415
+ let url = `/guilds/${guildId}/audit-logs`;
2416
+ if (options) {
2417
+ const params = new URLSearchParams();
2418
+ if (options.userId) params.append("user_id", options.userId);
2419
+ if (options.actionType !== void 0) params.append("action_type", options.actionType.toString());
2420
+ if (options.before) params.append("before", options.before);
2421
+ if (options.after) params.append("after", options.after);
2422
+ if (options.limit) params.append("limit", options.limit.toString());
2423
+ const qs = params.toString();
2424
+ if (qs) url += `?${qs}`;
2425
+ }
2426
+ const result = await this.rest.get(url);
2427
+ if (!result.ok) return result;
2428
+ return { ok: true, data: toCamelCase(result.data) };
2429
+ }
2430
+ async leave(guildId) {
2431
+ const result = await this.rest.delete(`/users/@me/guilds/${guildId}`);
2432
+ return result;
2433
+ }
2434
+ };
2435
+
2436
+ // src/managers/channel.ts
2437
+ var ChannelManager = class extends BaseManager {
2438
+ storeKey = "channels";
2439
+ endpoint(id) {
2440
+ return `/channels/${id}`;
2441
+ }
2442
+ build = buildChannel;
2443
+ async create(guildId, payload, reason) {
2444
+ const headers = {};
2445
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2446
+ const result = await this.rest.post(`/guilds/${guildId}/channels`, toSnakeCase(payload), headers);
2447
+ if (!result.ok) return result;
2448
+ const entity = this.build(result.data, guildId);
2449
+ this.store.channels.set(entity.id, entity);
2450
+ return { ok: true, data: entity };
2451
+ }
2452
+ async edit(channelId, payload, reason) {
2453
+ const headers = {};
2454
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2455
+ const result = await this.rest.patch(this.endpoint(channelId), toSnakeCase(payload), headers);
2456
+ if (!result.ok) return result;
2457
+ const entity = this.build(result.data);
2458
+ this.store.channels.set(entity.id, entity);
2459
+ return { ok: true, data: entity };
2460
+ }
2461
+ async delete(channelId, reason) {
2462
+ const headers = {};
2463
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2464
+ const result = await this.rest.delete(this.endpoint(channelId), headers);
2465
+ if (result.ok) this.store.channels.delete(channelId);
2466
+ return result;
2467
+ }
2468
+ async clone(channelId, options, reason) {
2469
+ const cached = this.store.channels.get(channelId);
2470
+ if (!cached) return { ok: false, status: 404, message: "Channel not found in cache" };
2471
+ const payload = { ...options };
2472
+ if (cached.name !== void 0) payload.name = cached.name;
2473
+ if (cached.type !== void 0) payload.type = cached.type;
2474
+ if (cached.topic !== void 0) payload.topic = cached.topic;
2475
+ if (cached.bitrate !== void 0) payload.bitrate = cached.bitrate;
2476
+ if (cached.userLimit !== void 0) payload.userLimit = cached.userLimit;
2477
+ if (cached.rateLimitPerUser !== void 0) payload.rateLimitPerUser = cached.rateLimitPerUser;
2478
+ if (cached.nsfw !== void 0) payload.nsfw = cached.nsfw;
2479
+ if (cached.position !== void 0) payload.position = cached.position;
2480
+ if (cached.parentId !== void 0) payload.parentId = cached.parentId;
2481
+ if (cached.permissionOverwrites !== void 0) payload.permissionOverwrites = cached.permissionOverwrites;
2482
+ if (!cached.guildId) return { ok: false, status: 400, message: "Cannot clone a DM channel" };
2483
+ return this.create(cached.guildId, payload, reason);
2484
+ }
2485
+ async setPositions(guildId, positions, reason) {
2486
+ const headers = {};
2487
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2488
+ const payload = positions.map((p) => ({
2489
+ id: p.id,
2490
+ ...p.position !== void 0 ? { position: p.position } : {},
2491
+ ...p.lockPermissions !== void 0 ? { lock_permissions: p.lockPermissions } : {},
2492
+ ...p.parentId !== void 0 ? { parent_id: p.parentId } : {}
2493
+ }));
2494
+ const result = await this.rest.patch(`/guilds/${guildId}/channels`, payload, headers);
2495
+ return result;
2496
+ }
2497
+ async updatePermissions(channelId, overwriteId, payload, reason) {
2498
+ const headers = {};
2499
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2500
+ return await this.rest.put(`/channels/${channelId}/permissions/${overwriteId}`, toSnakeCase(payload), headers);
2501
+ }
2502
+ async deletePermission(channelId, overwriteId, reason) {
2503
+ const headers = {};
2504
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2505
+ return await this.rest.delete(`/channels/${channelId}/permissions/${overwriteId}`, headers);
2506
+ }
2507
+ async sendTyping(channelId) {
2508
+ const result = await this.rest.post(`/channels/${channelId}/typing`);
2509
+ return result;
2510
+ }
2511
+ async getInvites(channelId) {
2512
+ const result = await this.rest.get(`/channels/${channelId}/invites`);
2513
+ if (!result.ok) return result;
2514
+ const invites = result.data.map((i) => buildInvite(i));
2515
+ return { ok: true, data: invites };
2516
+ }
2517
+ async createInvite(channelId, options, reason) {
2518
+ const headers = {};
2519
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2520
+ const payload = options ? toSnakeCase(options) : {};
2521
+ const result = await this.rest.post(`/channels/${channelId}/invites`, payload, headers);
2522
+ if (!result.ok) return result;
2523
+ return { ok: true, data: buildInvite(result.data) };
2524
+ }
2525
+ async followAnnouncementChannel(channelId, webhookChannelId) {
2526
+ const result = await this.rest.post(`/channels/${channelId}/followers`, { webhook_channel_id: webhookChannelId });
2527
+ if (!result.ok) return result;
2528
+ const data = result.data;
2529
+ return { ok: true, data: { channelId: data.channel_id, webhookId: data.webhook_id } };
2530
+ }
2531
+ async createThread(channelId, options, reason) {
2532
+ const headers = {};
2533
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2534
+ const result = await this.rest.post(`/channels/${channelId}/threads`, toSnakeCase(options), headers);
2535
+ if (!result.ok) return result;
2536
+ const channel = this.build(result.data);
2537
+ this.store.channels.set(channel.id, channel);
2538
+ return { ok: true, data: channel };
2539
+ }
2540
+ async createThreadFromMessage(channelId, messageId, options, reason) {
2541
+ const headers = {};
2542
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2543
+ const result = await this.rest.post(`/channels/${channelId}/messages/${messageId}/threads`, toSnakeCase(options), headers);
2544
+ if (!result.ok) return result;
2545
+ const channel = this.build(result.data);
2546
+ this.store.channels.set(channel.id, channel);
2547
+ return { ok: true, data: channel };
2548
+ }
2549
+ async joinThread(channelId) {
2550
+ const result = await this.rest.put(`/channels/${channelId}/thread-members/@me`);
2551
+ return result;
2552
+ }
2553
+ async leaveThread(channelId) {
2554
+ const result = await this.rest.delete(`/channels/${channelId}/thread-members/@me`);
2555
+ return result;
2556
+ }
2557
+ async listActiveThreads(guildId) {
2558
+ const result = await this.rest.get(`/guilds/${guildId}/threads/active`);
2559
+ if (!result.ok) return result;
2560
+ const data = result.data;
2561
+ const threads = data.threads.map((t) => {
2562
+ const channel = this.build(t, guildId);
2563
+ this.store.channels.set(channel.id, channel);
2564
+ return channel;
2565
+ });
2566
+ return { ok: true, data: { threads, members: data.members } };
2567
+ }
2568
+ async listArchivedThreads(channelId, type, options) {
2569
+ let url = `/channels/${channelId}/threads/archived/${type}`;
2570
+ if (options) {
2571
+ const params = new URLSearchParams();
2572
+ if (options.before) params.append("before", options.before);
2573
+ if (options.limit) params.append("limit", options.limit.toString());
2574
+ const qs = params.toString();
2575
+ if (qs) url += `?${qs}`;
2576
+ }
2577
+ const result = await this.rest.get(url);
2578
+ if (!result.ok) return result;
2579
+ const data = result.data;
2580
+ const threads = data.threads.map((t) => {
2581
+ const channel = this.build(t);
2582
+ this.store.channels.set(channel.id, channel);
2583
+ return channel;
2584
+ });
2585
+ return { ok: true, data: { threads, members: data.members, hasMore: data.has_more } };
2586
+ }
2587
+ async addThreadMember(channelId, userId) {
2588
+ const result = await this.rest.put(`/channels/${channelId}/thread-members/${userId}`);
2589
+ return result;
2590
+ }
2591
+ async removeThreadMember(channelId, userId) {
2592
+ const result = await this.rest.delete(`/channels/${channelId}/thread-members/${userId}`);
2593
+ return result;
2594
+ }
2595
+ async createForumThread(channelId, options, reason) {
2596
+ const headers = {};
2597
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2598
+ const messagePayload = {};
2599
+ if (options.message.content) messagePayload.content = options.message.content;
2600
+ if (options.message.embeds) {
2601
+ messagePayload.embeds = options.message.embeds.map(
2602
+ (e) => e && typeof e.toJSON === "function" ? e.toJSON() : e
2603
+ );
2604
+ }
2605
+ if (options.message.components) {
2606
+ messagePayload.components = options.message.components.map((c) => serializeComponent(c));
2607
+ }
2608
+ const payload = {
2609
+ name: options.name,
2610
+ message: messagePayload,
2611
+ ...options.autoArchiveDuration !== void 0 ? { auto_archive_duration: options.autoArchiveDuration } : {},
2612
+ ...options.rateLimitPerUser !== void 0 ? { rate_limit_per_user: options.rateLimitPerUser } : {},
2613
+ ...options.appliedTags ? { applied_tags: options.appliedTags } : {}
2614
+ };
2615
+ let result;
2616
+ if (options.message.files && options.message.files.length > 0) {
2617
+ result = await this.rest.requestWithFiles("POST", `/channels/${channelId}/threads`, payload, options.message.files, headers);
2153
2618
  } else {
2154
- this._client.on("READY", async () => {
2155
- await this._client.rest.put(`/applications/${this._client.user.id}/commands`, payload);
2156
- });
2619
+ result = await this.rest.post(`/channels/${channelId}/threads`, payload, headers);
2157
2620
  }
2621
+ if (!result.ok) return result;
2622
+ const channel = this.build(result.data);
2623
+ this.store.channels.set(channel.id, channel);
2624
+ return { ok: true, data: channel };
2158
2625
  }
2159
- _transformCommand(cmd) {
2160
- const mapType = (t) => {
2161
- switch (t) {
2162
- case "string":
2163
- return 3;
2164
- case "integer":
2165
- return 4;
2166
- case "boolean":
2167
- return 5;
2168
- case "user":
2169
- return 6;
2170
- case "channel":
2171
- return 7;
2172
- case "role":
2173
- return 8;
2174
- case "number":
2175
- return 10;
2176
- default:
2177
- return 3;
2626
+ };
2627
+
2628
+ // src/managers/message.ts
2629
+ var MessageManager = class {
2630
+ constructor(rest, store) {
2631
+ this.rest = rest;
2632
+ this.store = store;
2633
+ }
2634
+ rest;
2635
+ store;
2636
+ async fetch(channelId, messageId, force = false) {
2637
+ if (!force) {
2638
+ const cached = this.store.messages.get(messageId);
2639
+ if (cached) return { ok: true, data: cached };
2640
+ }
2641
+ const result = await this.rest.get(`/channels/${channelId}/messages/${messageId}`);
2642
+ if (!result.ok) return result;
2643
+ const message = buildMessage(result.data, this.store);
2644
+ this.store.messages.set(message.id, message);
2645
+ return { ok: true, data: message };
2646
+ }
2647
+ async send(channelId, payload) {
2648
+ const data = typeof payload === "string" ? { content: payload } : { ...payload };
2649
+ let files;
2650
+ if (typeof payload === "object") {
2651
+ if (payload.embeds) {
2652
+ data.embeds = payload.embeds.map((e) => e && typeof e.toJSON === "function" ? e.toJSON() : e);
2178
2653
  }
2179
- };
2180
- const options = [];
2181
- if (cmd.subcommands) {
2182
- for (const [subName, subDefRaw] of Object.entries(cmd.subcommands)) {
2183
- const subDef = subDefRaw;
2184
- const subOpts = [];
2185
- if (subDef.options) {
2186
- for (const [optName, optDef] of Object.entries(subDef.options)) {
2187
- subOpts.push({
2188
- type: mapType(optDef.type),
2189
- name: optName,
2190
- description: optDef.description,
2191
- required: optDef.required,
2192
- choices: optDef.choices,
2193
- min_value: optDef.min,
2194
- max_value: optDef.max
2195
- });
2196
- }
2197
- }
2198
- options.push({
2199
- type: 1 /* SUB_COMMAND */,
2200
- name: subName,
2201
- description: subDef.description,
2202
- options: subOpts
2203
- });
2654
+ if (payload.components) {
2655
+ data.components = payload.components.map((c) => serializeComponent(c));
2204
2656
  }
2205
- } else if (cmd.options) {
2206
- for (const [optName, optDef] of Object.entries(cmd.options)) {
2207
- options.push({
2208
- type: mapType(optDef.type),
2209
- name: optName,
2210
- description: optDef.description,
2211
- required: optDef.required,
2212
- choices: optDef.choices,
2213
- min_value: optDef.min,
2214
- max_value: optDef.max
2215
- });
2657
+ if (payload.reply) {
2658
+ data.message_reference = { message_id: payload.reply.messageId, fail_if_not_exists: payload.reply.failIfNotExists ?? true };
2659
+ delete data.reply;
2660
+ }
2661
+ if (payload.poll) {
2662
+ data.poll = {
2663
+ question: payload.poll.question,
2664
+ answers: payload.poll.answers.map((a) => ({
2665
+ ...a.answerId !== void 0 ? { answer_id: a.answerId } : {},
2666
+ poll_media: a.pollMedia
2667
+ })),
2668
+ ...payload.poll.duration !== void 0 ? { duration: payload.poll.duration } : {},
2669
+ ...payload.poll.allowMultiselect !== void 0 ? { allow_multiselect: payload.poll.allowMultiselect } : {},
2670
+ ...payload.poll.layoutType !== void 0 ? { layout_type: payload.poll.layoutType } : {}
2671
+ };
2672
+ }
2673
+ if (payload.tts !== void 0) data.tts = payload.tts;
2674
+ if (payload.flags !== void 0) data.flags = payload.flags;
2675
+ if (payload.nonce !== void 0) data.nonce = payload.nonce;
2676
+ if (payload.enforceNonce !== void 0) data.enforce_nonce = payload.enforceNonce;
2677
+ if (payload.stickerIds && payload.stickerIds.length > 0) {
2678
+ data.sticker_ids = payload.stickerIds;
2679
+ delete data.stickerIds;
2680
+ }
2681
+ if (payload.files && payload.files.length > 0) {
2682
+ files = payload.files;
2683
+ delete data.files;
2216
2684
  }
2217
2685
  }
2218
- return {
2219
- name: cmd.name,
2220
- description: cmd.description,
2221
- options: options.length ? options : void 0
2222
- };
2686
+ let result;
2687
+ if (files && files.length > 0) {
2688
+ result = await this.rest.requestWithFiles("POST", `/channels/${channelId}/messages`, data, files);
2689
+ } else {
2690
+ result = await this.rest.post(`/channels/${channelId}/messages`, data);
2691
+ }
2692
+ if (!result.ok) return result;
2693
+ const message = buildMessage(result.data, this.store);
2694
+ this.store.messages.set(message.id, message);
2695
+ return { ok: true, data: message };
2223
2696
  }
2224
- async handleInteraction(raw) {
2225
- if (raw.type === 3 /* MESSAGE_COMPONENT */) return this._handleComponentInteraction(raw);
2226
- if (raw.type === 5 /* MODAL_SUBMIT */) return this._handleModalInteraction(raw);
2227
- if (raw.type !== 2 /* APPLICATION_COMMAND */) return;
2228
- const name = raw.data.name;
2229
- const command = this._commands.get(name);
2230
- if (!command) return;
2231
- const parsedOptions = {};
2232
- let targetExecute = command.execute;
2233
- const rawOptions = raw.data.options || [];
2234
- let actualOptions = rawOptions;
2235
- if (rawOptions.length > 0 && rawOptions[0].type === 1 /* SUB_COMMAND */) {
2236
- const subcommandName = rawOptions[0].name;
2237
- actualOptions = rawOptions[0].options || [];
2238
- if (command.subcommands && command.subcommands[subcommandName]) {
2239
- targetExecute = command.subcommands[subcommandName].execute;
2697
+ async edit(channelId, messageId, payload) {
2698
+ const data = typeof payload === "string" ? { content: payload } : { ...payload };
2699
+ let files;
2700
+ if (typeof payload === "object") {
2701
+ if (payload.embeds) {
2702
+ data.embeds = payload.embeds.map((e) => e && typeof e.toJSON === "function" ? e.toJSON() : e);
2240
2703
  }
2241
- }
2242
- for (const opt2 of actualOptions) {
2243
- if (opt2.type === 6 /* USER */ && raw.data.resolved?.users?.[opt2.value]) {
2244
- parsedOptions[opt2.name] = resolveUser(opt2.value, this._client.cache);
2245
- } else if (opt2.type === 7 /* CHANNEL */ && raw.data.resolved?.channels?.[opt2.value]) {
2246
- parsedOptions[opt2.name] = resolveChannel(opt2.value, this._client.cache);
2247
- } else if (opt2.type === 8 /* ROLE */ && raw.data.resolved?.roles?.[opt2.value]) {
2248
- parsedOptions[opt2.name] = resolveRole(opt2.value, this._client.cache);
2249
- } else {
2250
- parsedOptions[opt2.name] = opt2.value;
2704
+ if (payload.components) {
2705
+ data.components = payload.components.map((c) => serializeComponent(c));
2251
2706
  }
2252
- }
2253
- const member = raw.member || {};
2254
- const userRaw = member.user || raw.user;
2255
- const user = buildUser(userRaw);
2256
- const ctx = new CommandContext(
2257
- this._client,
2258
- raw,
2259
- parsedOptions,
2260
- user,
2261
- raw.guild_id ? resolveGuild(raw.guild_id, this._client.cache) : void 0,
2262
- raw.channel_id ? resolveChannel(raw.channel_id, this._client.cache) : void 0
2263
- );
2264
- if (targetExecute) {
2265
- try {
2266
- await targetExecute(ctx);
2267
- } catch (err) {
2268
- console.error(`[Chameleon] Error executing command ${name}:`, err);
2707
+ if (payload.files && payload.files.length > 0) {
2708
+ files = payload.files;
2709
+ delete data.files;
2269
2710
  }
2270
2711
  }
2712
+ let result;
2713
+ if (files && files.length > 0) {
2714
+ result = await this.rest.requestWithFiles("PATCH", `/channels/${channelId}/messages/${messageId}`, data, files);
2715
+ } else {
2716
+ result = await this.rest.patch(`/channels/${channelId}/messages/${messageId}`, data);
2717
+ }
2718
+ if (!result.ok) return result;
2719
+ const oldMsg = this.store.messages.get(messageId);
2720
+ const message = buildMessage(result.data, this.store, oldMsg);
2721
+ this.store.messages.set(message.id, message);
2722
+ return { ok: true, data: message };
2271
2723
  }
2272
- async _handleComponentInteraction(raw) {
2273
- const customId = raw.data.custom_id;
2274
- const handler = this._components.find(
2275
- (h) => typeof h.customId === "string" ? h.customId === customId : h.customId.test(customId)
2276
- );
2277
- if (!handler) return;
2278
- const userRaw = raw.member?.user || raw.user;
2279
- const user = buildUser(userRaw);
2280
- const ctx = new ComponentContext(
2281
- this._client,
2282
- raw,
2283
- user,
2284
- raw.guild_id ? resolveGuild(raw.guild_id, this._client.cache) : void 0,
2285
- raw.channel_id ? resolveChannel(raw.channel_id, this._client.cache) : void 0
2286
- );
2287
- if (raw.data.component_type === 3 /* STRING_SELECT */ || raw.data.component_type === 5 /* USER_SELECT */ || raw.data.component_type === 6 /* ROLE_SELECT */ || raw.data.component_type === 7 /* MENTIONABLE_SELECT */ || raw.data.component_type === 8 /* CHANNEL_SELECT */) {
2288
- ctx._values = raw.data.values || [];
2724
+ async delete(channelId, messageId) {
2725
+ const result = await this.rest.delete(`/channels/${channelId}/messages/${messageId}`);
2726
+ if (result.ok) {
2727
+ this.store.messages.delete(messageId);
2289
2728
  }
2290
- try {
2291
- await handler.execute(ctx);
2292
- } catch (err) {
2293
- console.error(`[Chameleon] Error executing component ${customId}:`, err);
2729
+ return result;
2730
+ }
2731
+ async list(channelId, options) {
2732
+ let url = `/channels/${channelId}/messages`;
2733
+ if (options) {
2734
+ const params = new URLSearchParams();
2735
+ if (options.limit) params.append("limit", options.limit.toString());
2736
+ if (options.before) params.append("before", options.before);
2737
+ if (options.after) params.append("after", options.after);
2738
+ if (options.around) params.append("around", options.around);
2739
+ const qs = params.toString();
2740
+ if (qs) url += `?${qs}`;
2294
2741
  }
2742
+ const result = await this.rest.get(url);
2743
+ if (!result.ok) return result;
2744
+ const messages = result.data.map((msgData) => {
2745
+ const msg = buildMessage(msgData, this.store);
2746
+ this.store.messages.set(msg.id, msg);
2747
+ return msg;
2748
+ });
2749
+ return { ok: true, data: messages };
2295
2750
  }
2296
- async _handleModalInteraction(raw) {
2297
- const customId = raw.data.custom_id;
2298
- const handler = this._modals.find(
2299
- (h) => typeof h.customId === "string" ? h.customId === customId : h.customId.test(customId)
2300
- );
2301
- if (!handler) return;
2302
- const userRaw = raw.member?.user || raw.user;
2303
- const user = buildUser(userRaw);
2304
- const ctx = new ModalContext(
2305
- this._client,
2306
- raw,
2307
- user,
2308
- raw.guild_id ? resolveGuild(raw.guild_id, this._client.cache) : void 0,
2309
- raw.channel_id ? resolveChannel(raw.channel_id, this._client.cache) : void 0
2310
- );
2311
- try {
2312
- await handler.execute(ctx);
2313
- } catch (err) {
2314
- console.error(`[Chameleon] Error executing modal ${customId}:`, err);
2751
+ async react(channelId, messageId, emoji) {
2752
+ const encodedEmoji = encodeURIComponent(emoji);
2753
+ const result = await this.rest.put(`/channels/${channelId}/messages/${messageId}/reactions/${encodedEmoji}/@me`);
2754
+ return result;
2755
+ }
2756
+ async removeReaction(channelId, messageId, emoji, userId = "@me") {
2757
+ const encodedEmoji = encodeURIComponent(emoji);
2758
+ const result = await this.rest.delete(`/channels/${channelId}/messages/${messageId}/reactions/${encodedEmoji}/${userId}`);
2759
+ return result;
2760
+ }
2761
+ async removeAllReactions(channelId, messageId, emoji) {
2762
+ let url = `/channels/${channelId}/messages/${messageId}/reactions`;
2763
+ if (emoji) url += `/${encodeURIComponent(emoji)}`;
2764
+ const result = await this.rest.delete(url);
2765
+ return result;
2766
+ }
2767
+ async getReactions(channelId, messageId, emoji, options) {
2768
+ let url = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`;
2769
+ if (options) {
2770
+ const params = new URLSearchParams();
2771
+ if (options.after) params.append("after", options.after);
2772
+ if (options.limit) params.append("limit", options.limit.toString());
2773
+ if (options.type !== void 0) params.append("type", options.type.toString());
2774
+ const qs = params.toString();
2775
+ if (qs) url += `?${qs}`;
2315
2776
  }
2777
+ const result = await this.rest.get(url);
2778
+ if (!result.ok) return result;
2779
+ const users = result.data.map((userData) => {
2780
+ const user = buildUser(userData);
2781
+ this.store.users.set(user.id, user);
2782
+ return user;
2783
+ });
2784
+ return { ok: true, data: users };
2785
+ }
2786
+ async pin(channelId, messageId) {
2787
+ const result = await this.rest.put(`/channels/${channelId}/pins/${messageId}`);
2788
+ return result;
2789
+ }
2790
+ async unpin(channelId, messageId) {
2791
+ const result = await this.rest.delete(`/channels/${channelId}/pins/${messageId}`);
2792
+ return result;
2793
+ }
2794
+ async getPins(channelId) {
2795
+ const result = await this.rest.get(`/channels/${channelId}/pins`);
2796
+ if (!result.ok) return result;
2797
+ const messages = result.data.map((msgData) => {
2798
+ const msg = buildMessage(msgData, this.store);
2799
+ this.store.messages.set(msg.id, msg);
2800
+ return msg;
2801
+ });
2802
+ return { ok: true, data: messages };
2803
+ }
2804
+ async bulkDelete(channelId, messageIds) {
2805
+ const result = await this.rest.post(`/channels/${channelId}/messages/bulk-delete`, { messages: messageIds });
2806
+ if (result.ok) {
2807
+ for (const id of messageIds) {
2808
+ this.store.messages.delete(id);
2809
+ }
2810
+ }
2811
+ return result;
2812
+ }
2813
+ async forward(channelId, messageId) {
2814
+ const result = await this.rest.post(`/channels/${channelId}/messages/${messageId}/crosspost`);
2815
+ if (!result.ok) return result;
2816
+ const oldMsg = this.store.messages.get(messageId);
2817
+ const message = buildMessage(result.data, this.store, oldMsg);
2818
+ this.store.messages.set(message.id, message);
2819
+ return { ok: true, data: message };
2820
+ }
2821
+ async endPoll(channelId, messageId) {
2822
+ const result = await this.rest.post(`/channels/${channelId}/polls/${messageId}/expire`);
2823
+ if (!result.ok) return result;
2824
+ const message = buildMessage(result.data, this.store);
2825
+ this.store.messages.set(message.id, message);
2826
+ return { ok: true, data: message };
2827
+ }
2828
+ async getPollAnswerVoters(channelId, messageId, answerId, options) {
2829
+ let url = `/channels/${channelId}/polls/${messageId}/answers/${answerId}`;
2830
+ if (options) {
2831
+ const params = new URLSearchParams();
2832
+ if (options.after) params.append("after", options.after);
2833
+ if (options.limit) params.append("limit", options.limit.toString());
2834
+ const qs = params.toString();
2835
+ if (qs) url += `?${qs}`;
2836
+ }
2837
+ const result = await this.rest.get(url);
2838
+ if (!result.ok) return result;
2839
+ const data = result.data;
2840
+ const users = data.users.map((u) => {
2841
+ const user = buildUser(u);
2842
+ this.store.users.set(user.id, user);
2843
+ return user;
2844
+ });
2845
+ return { ok: true, data: users };
2316
2846
  }
2317
2847
  };
2318
2848
 
2319
- // src/components/context.ts
2320
- var ComponentContext2 = class {
2321
- user;
2322
- guild;
2323
- channel;
2324
- interactionId;
2325
- interactionToken;
2326
- customId;
2327
- values;
2328
- fields;
2329
- _client;
2330
- _deferred = false;
2331
- _replied = false;
2332
- constructor(client, rawInteraction, user, guild, channel) {
2333
- this._client = client;
2334
- this.interactionId = rawInteraction.id;
2335
- this.interactionToken = rawInteraction.token;
2336
- this.customId = rawInteraction.data?.custom_id;
2337
- this.user = user;
2338
- this.guild = guild;
2339
- this.channel = channel;
2340
- this.values = rawInteraction.data?.values ?? [];
2341
- const fields = {};
2342
- if (rawInteraction.data?.components) {
2343
- for (const row of rawInteraction.data.components) {
2344
- for (const comp of row.components) {
2345
- fields[comp.custom_id] = comp.value;
2849
+ // src/managers/collector.ts
2850
+ var CollectorManager = class {
2851
+ constructor(client) {
2852
+ this.client = client;
2853
+ }
2854
+ client;
2855
+ /**
2856
+ * Waits for a specified number of messages in a given channel that pass the filter, if the time limit
2857
+ * is reached, resolves with the messages collected so far
2858
+ */
2859
+ async awaitMessages(channelId, options = {}) {
2860
+ const { filter, max = 1, time = 15e3 } = options;
2861
+ return new Promise((resolve4) => {
2862
+ const messages = [];
2863
+ let timeoutId = null;
2864
+ const handler = (data) => {
2865
+ const msg = data.message;
2866
+ if (msg.channelId !== channelId) return;
2867
+ if (filter && !filter(msg)) return;
2868
+ messages.push(msg);
2869
+ if (messages.length >= max) {
2870
+ cleanup();
2871
+ resolve4(messages);
2346
2872
  }
2873
+ };
2874
+ const cleanup = () => {
2875
+ if (timeoutId) clearTimeout(timeoutId);
2876
+ this.client.off("MESSAGE_CREATE", handler);
2877
+ };
2878
+ this.client.on("MESSAGE_CREATE", handler);
2879
+ if (time > 0) {
2880
+ timeoutId = setTimeout(() => {
2881
+ cleanup();
2882
+ resolve4(messages);
2883
+ }, time);
2884
+ }
2885
+ });
2886
+ }
2887
+ /**
2888
+ * waits for a single component interaction on a specific message,
2889
+ * resolves with the ComponentContext if successful, or null if it timed out
2890
+ */
2891
+ async awaitComponent(messageId, options = {}) {
2892
+ const { filter, time = 15e3 } = options;
2893
+ return new Promise((resolve4) => {
2894
+ let timeoutId = null;
2895
+ const handler = (data) => {
2896
+ if (data.type !== "INTERACTION_CREATE") return;
2897
+ const interaction = data.interaction;
2898
+ const raw = interaction;
2899
+ if (interaction.type !== 3 /* MESSAGE_COMPONENT */) return;
2900
+ if (interaction.message?.id !== messageId) return;
2901
+ const userRaw = interaction.member?.user || interaction.user;
2902
+ const user = buildUser(userRaw);
2903
+ const ctx = new ComponentContext(
2904
+ this.client,
2905
+ raw,
2906
+ user,
2907
+ interaction.guildId ? resolveGuild(interaction.guildId, this.client) : void 0,
2908
+ interaction.channelId ? resolveChannel(interaction.channelId, this.client) : void 0
2909
+ );
2910
+ if (filter && !filter(ctx)) return;
2911
+ cleanup();
2912
+ resolve4(ctx);
2913
+ };
2914
+ const cleanup = () => {
2915
+ if (timeoutId) clearTimeout(timeoutId);
2916
+ this.client.off("INTERACTION_CREATE", handler);
2917
+ };
2918
+ this.client.on("INTERACTION_CREATE", handler);
2919
+ if (time > 0) {
2920
+ timeoutId = setTimeout(() => {
2921
+ cleanup();
2922
+ resolve4(null);
2923
+ }, time);
2924
+ }
2925
+ });
2926
+ }
2927
+ };
2928
+
2929
+ // src/managers/webhook.ts
2930
+ var WebhookManager = class {
2931
+ constructor(rest, store) {
2932
+ this.rest = rest;
2933
+ this.store = store;
2934
+ }
2935
+ rest;
2936
+ store;
2937
+ async fetch(webhookId, token) {
2938
+ const url = token ? `/webhooks/${webhookId}/${token}` : `/webhooks/${webhookId}`;
2939
+ const result = await this.rest.get(url);
2940
+ if (!result.ok) return result;
2941
+ return { ok: true, data: buildWebhook(result.data) };
2942
+ }
2943
+ async fetchByChannel(channelId) {
2944
+ const result = await this.rest.get(`/channels/${channelId}/webhooks`);
2945
+ if (!result.ok) return result;
2946
+ const webhooks = result.data.map((w) => buildWebhook(w));
2947
+ return { ok: true, data: webhooks };
2948
+ }
2949
+ async fetchByGuild(guildId) {
2950
+ const result = await this.rest.get(`/guilds/${guildId}/webhooks`);
2951
+ if (!result.ok) return result;
2952
+ const webhooks = result.data.map((w) => buildWebhook(w));
2953
+ return { ok: true, data: webhooks };
2954
+ }
2955
+ async create(channelId, payload, reason) {
2956
+ const headers = {};
2957
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2958
+ const result = await this.rest.post(`/channels/${channelId}/webhooks`, toSnakeCase(payload), headers);
2959
+ if (!result.ok) return result;
2960
+ return { ok: true, data: buildWebhook(result.data) };
2961
+ }
2962
+ async edit(webhookId, payload, token, reason) {
2963
+ const headers = {};
2964
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2965
+ const url = token ? `/webhooks/${webhookId}/${token}` : `/webhooks/${webhookId}`;
2966
+ const result = await this.rest.patch(url, toSnakeCase(payload), headers);
2967
+ if (!result.ok) return result;
2968
+ return { ok: true, data: buildWebhook(result.data) };
2969
+ }
2970
+ async delete(webhookId, token, reason) {
2971
+ const headers = {};
2972
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2973
+ const url = token ? `/webhooks/${webhookId}/${token}` : `/webhooks/${webhookId}`;
2974
+ const result = await this.rest.delete(url, headers);
2975
+ return result;
2976
+ }
2977
+ async execute(webhookId, token, payload, options) {
2978
+ const data = typeof payload === "string" ? { content: payload } : { ...toSnakeCase(payload) };
2979
+ let files;
2980
+ if (typeof payload === "object") {
2981
+ if (payload.embeds) {
2982
+ data.embeds = payload.embeds.map((e) => e && typeof e.toJSON === "function" ? e.toJSON() : e);
2983
+ }
2984
+ if (payload.components) {
2985
+ data.components = payload.components.map((c) => serializeComponent(c));
2986
+ }
2987
+ if (payload.poll) {
2988
+ data.poll = {
2989
+ question: payload.poll.question,
2990
+ answers: payload.poll.answers.map((a) => ({
2991
+ ...a.answerId !== void 0 ? { answer_id: a.answerId } : {},
2992
+ poll_media: a.pollMedia
2993
+ })),
2994
+ ...payload.poll.duration !== void 0 ? { duration: payload.poll.duration } : {},
2995
+ ...payload.poll.allowMultiselect !== void 0 ? { allow_multiselect: payload.poll.allowMultiselect } : {},
2996
+ ...payload.poll.layoutType !== void 0 ? { layout_type: payload.poll.layoutType } : {}
2997
+ };
2998
+ }
2999
+ if (payload.files && payload.files.length > 0) {
3000
+ files = payload.files;
3001
+ delete data.files;
2347
3002
  }
2348
3003
  }
2349
- this.fields = fields;
3004
+ let url = `/webhooks/${webhookId}/${token}`;
3005
+ const params = new URLSearchParams();
3006
+ if (options?.wait) params.append("wait", "true");
3007
+ if (options?.threadId) params.append("thread_id", options.threadId);
3008
+ const qs = params.toString();
3009
+ if (qs) url += `?${qs}`;
3010
+ let result;
3011
+ if (files && files.length > 0) {
3012
+ result = await this.rest.requestWithFiles("POST", url, data, files);
3013
+ } else {
3014
+ result = await this.rest.post(url, data);
3015
+ }
3016
+ if (!result.ok) return result;
3017
+ if (options?.wait && result.data) {
3018
+ const message = buildMessage(result.data, this.store);
3019
+ this.store.messages.set(message.id, message);
3020
+ return { ok: true, data: message };
3021
+ }
3022
+ return { ok: true, data: void 0 };
2350
3023
  }
2351
- get replied() {
2352
- return this._replied;
3024
+ };
3025
+
3026
+ // src/managers/invite.ts
3027
+ var InviteManager = class {
3028
+ constructor(rest) {
3029
+ this.rest = rest;
2353
3030
  }
2354
- get deferred() {
2355
- return this._deferred;
3031
+ rest;
3032
+ async fetch(code, options) {
3033
+ let url = `/invites/${code}`;
3034
+ if (options) {
3035
+ const params = new URLSearchParams();
3036
+ if (options.withCounts) params.append("with_counts", "true");
3037
+ if (options.withExpiration) params.append("with_expiration", "true");
3038
+ if (options.guildScheduledEventId) params.append("guild_scheduled_event_id", options.guildScheduledEventId);
3039
+ const qs = params.toString();
3040
+ if (qs) url += `?${qs}`;
3041
+ }
3042
+ const result = await this.rest.get(url);
3043
+ if (!result.ok) return result;
3044
+ return { ok: true, data: buildInvite(result.data) };
2356
3045
  }
2357
- async reply(payload) {
2358
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2359
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
2360
- if (typeof payload === "object" && payload.ephemeral) data.flags = 64;
2361
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2362
- type: 4 /* CHANNEL_MESSAGE_WITH_SOURCE */,
2363
- data
2364
- });
2365
- this._replied = true;
3046
+ async delete(code, reason) {
3047
+ const headers = {};
3048
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
3049
+ const result = await this.rest.delete(`/invites/${code}`, headers);
3050
+ if (!result.ok) return result;
3051
+ return { ok: true, data: buildInvite(result.data) };
2366
3052
  }
2367
- async defer(options) {
2368
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2369
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2370
- type: 5 /* DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE */,
2371
- data: {
2372
- flags: options?.ephemeral ? 64 : 0
2373
- }
2374
- });
2375
- this._deferred = true;
3053
+ };
3054
+
3055
+ // src/managers/automod.ts
3056
+ var AutoModerationManager = class {
3057
+ constructor(rest, store) {
3058
+ this.rest = rest;
3059
+ this.store = store;
2376
3060
  }
2377
- async update(payload) {
2378
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2379
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
2380
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2381
- type: 7 /* UPDATE_MESSAGE */,
2382
- data
3061
+ rest;
3062
+ store;
3063
+ async list(guildId) {
3064
+ const result = await this.rest.get(`/guilds/${guildId}/auto-moderation/rules`);
3065
+ if (!result.ok) return result;
3066
+ const rules = result.data.map((r) => {
3067
+ const rule = buildAutoModRule(r);
3068
+ this.store.autoModRules.set(rule.id, rule);
3069
+ return rule;
2383
3070
  });
2384
- this._replied = true;
3071
+ return { ok: true, data: rules };
2385
3072
  }
2386
- async deferUpdate() {
2387
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2388
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2389
- type: 6 /* DEFERRED_UPDATE_MESSAGE */
2390
- });
2391
- this._deferred = true;
3073
+ async fetch(guildId, ruleId) {
3074
+ const cached = this.store.autoModRules.get(ruleId);
3075
+ if (cached) return { ok: true, data: cached };
3076
+ const result = await this.rest.get(`/guilds/${guildId}/auto-moderation/rules/${ruleId}`);
3077
+ if (!result.ok) return result;
3078
+ const rule = buildAutoModRule(result.data);
3079
+ this.store.autoModRules.set(rule.id, rule);
3080
+ return { ok: true, data: rule };
2392
3081
  }
2393
- async followUp(payload) {
2394
- if (!this._deferred && !this._replied) throw new Error("Interaction not acknowledged. Use reply or defer first.");
2395
- const data = typeof payload === "string" ? { content: payload } : { ...payload };
2396
- if (typeof payload === "object" && payload.ephemeral) data.flags = 64;
2397
- await this._client.rest.post(`/webhooks/${this._client.user?.id}/${this.interactionToken}`, data);
3082
+ async create(guildId, payload, reason) {
3083
+ const headers = {};
3084
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
3085
+ const result = await this.rest.post(`/guilds/${guildId}/auto-moderation/rules`, toSnakeCase(payload), headers);
3086
+ if (!result.ok) return result;
3087
+ const rule = buildAutoModRule(result.data);
3088
+ this.store.autoModRules.set(rule.id, rule);
3089
+ return { ok: true, data: rule };
2398
3090
  }
2399
- async showModal(modal) {
2400
- if (this._replied || this._deferred) throw new Error("Interaction already acknowledged.");
2401
- await this._client.rest.post(`/interactions/${this.interactionId}/${this.interactionToken}/callback`, {
2402
- type: 9 /* MODAL */,
2403
- data: modal.type === "modal" ? buildModalPayload(modal) : modal
2404
- });
2405
- this._replied = true;
3091
+ async edit(guildId, ruleId, payload, reason) {
3092
+ const headers = {};
3093
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
3094
+ const result = await this.rest.patch(`/guilds/${guildId}/auto-moderation/rules/${ruleId}`, toSnakeCase(payload), headers);
3095
+ if (!result.ok) return result;
3096
+ const rule = buildAutoModRule(result.data);
3097
+ this.store.autoModRules.set(rule.id, rule);
3098
+ return { ok: true, data: rule };
2406
3099
  }
2407
- };
2408
- function buildModalPayload(def) {
2409
- return {
2410
- custom_id: def.customId,
2411
- title: def.title,
2412
- components: def.fields.map((f) => ({
2413
- type: 1 /* ACTION_ROW */,
2414
- components: [{
2415
- type: 4 /* TEXT_INPUT */,
2416
- custom_id: f.id,
2417
- style: f.type,
2418
- // 1 short, 2 paragraph
2419
- label: f.label,
2420
- required: f.required,
2421
- min_length: f.minLength,
2422
- max_length: f.maxLength,
2423
- placeholder: f.placeholder,
2424
- value: f.value
2425
- }]
2426
- }))
2427
- };
2428
- }
2429
-
2430
- // src/components/define.ts
2431
- function resolveButtonStyle(style) {
2432
- if (typeof style === "number") return style;
2433
- const map = { primary: 1, secondary: 2, success: 3, danger: 4, link: 5, premium: 6 };
2434
- return map[style] ?? 1;
2435
- }
2436
- function defineButton(def) {
2437
- return { ...def, type: "button" };
2438
- }
2439
- function defineStringSelect(def) {
2440
- return { ...def, type: "string_select" };
2441
- }
2442
- function defineUserSelect(def) {
2443
- return { ...def, type: "user_select" };
2444
- }
2445
- function defineRoleSelect(def) {
2446
- return { ...def, type: "role_select" };
2447
- }
2448
- function defineChannelSelect(def) {
2449
- return { ...def, type: "channel_select" };
2450
- }
2451
- function defineMentionableSelect(def) {
2452
- return { ...def, type: "mentionable_select" };
2453
- }
2454
- var field = {
2455
- short: (id, label, options) => ({
2456
- id,
2457
- type: 1 /* SHORT */,
2458
- label,
2459
- required: options?.required ?? true,
2460
- ...options
2461
- }),
2462
- paragraph: (id, label, options) => ({
2463
- id,
2464
- type: 2 /* PARAGRAPH */,
2465
- label,
2466
- required: options?.required ?? true,
2467
- ...options
2468
- })
2469
- };
2470
- function defineModal(def) {
2471
- return { ...def, type: "modal" };
2472
- }
2473
-
2474
- // src/components/actionRow.ts
2475
- var ActionRow = {
2476
- of: (...components) => {
2477
- return {
2478
- type: 1 /* ACTION_ROW */,
2479
- components: components.map((c) => {
2480
- if (c.type === "button") {
2481
- return {
2482
- type: 2 /* BUTTON */,
2483
- custom_id: c.customId,
2484
- url: c.url,
2485
- label: c.label,
2486
- style: resolveButtonStyle(c.style),
2487
- disabled: c.disabled,
2488
- emoji: c.emoji,
2489
- sku_id: c.skuId
2490
- };
2491
- }
2492
- if (c.type === "string_select") {
2493
- return {
2494
- type: 3 /* STRING_SELECT */,
2495
- custom_id: c.customId,
2496
- options: c.options,
2497
- placeholder: c.placeholder,
2498
- min_values: c.minValues,
2499
- max_values: c.maxValues,
2500
- disabled: c.disabled
2501
- };
2502
- }
2503
- if (c.type === "user_select") {
2504
- return { type: 5 /* USER_SELECT */, custom_id: c.customId, placeholder: c.placeholder, min_values: c.minValues, max_values: c.maxValues, disabled: c.disabled };
2505
- }
2506
- if (c.type === "role_select") {
2507
- return { type: 6 /* ROLE_SELECT */, custom_id: c.customId, placeholder: c.placeholder, min_values: c.minValues, max_values: c.maxValues, disabled: c.disabled };
2508
- }
2509
- if (c.type === "mentionable_select") {
2510
- return { type: 7 /* MENTIONABLE_SELECT */, custom_id: c.customId, placeholder: c.placeholder, min_values: c.minValues, max_values: c.maxValues, disabled: c.disabled };
2511
- }
2512
- if (c.type === "channel_select") {
2513
- return { type: 8 /* CHANNEL_SELECT */, custom_id: c.customId, channel_types: c.channelTypes, placeholder: c.placeholder, min_values: c.minValues, max_values: c.maxValues, disabled: c.disabled };
2514
- }
2515
- if (c.type === 1 /* SHORT */ || c.type === 2 /* PARAGRAPH */) {
2516
- return {
2517
- type: 4 /* TEXT_INPUT */,
2518
- custom_id: c.id,
2519
- style: c.type,
2520
- label: c.label,
2521
- required: c.required,
2522
- min_length: c.minLength,
2523
- max_length: c.maxLength,
2524
- placeholder: c.placeholder,
2525
- value: c.value
2526
- };
2527
- }
2528
- return c;
2529
- }).map((obj) => {
2530
- const clean = {};
2531
- for (const [k, v] of Object.entries(obj)) {
2532
- if (v !== void 0) clean[k] = v;
2533
- }
2534
- return clean;
2535
- })
2536
- };
3100
+ async delete(guildId, ruleId, reason) {
3101
+ const headers = {};
3102
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
3103
+ const result = await this.rest.delete(`/guilds/${guildId}/auto-moderation/rules/${ruleId}`, headers);
3104
+ if (result.ok) this.store.autoModRules.delete(ruleId);
3105
+ return result;
2537
3106
  }
2538
3107
  };
2539
3108
 
2540
- // src/components/manager.ts
2541
- var ComponentManager = class {
2542
- constructor(client) {
2543
- this.client = client;
3109
+ // src/managers/scheduled.ts
3110
+ var ScheduledEventManager = class {
3111
+ constructor(rest, store) {
3112
+ this.rest = rest;
3113
+ this.store = store;
2544
3114
  }
2545
- client;
2546
- handlers = /* @__PURE__ */ new Map();
2547
- register(...components) {
2548
- for (const comp of components) {
2549
- if (comp.customId) {
2550
- this.handlers.set(comp.customId, comp);
2551
- }
2552
- }
3115
+ rest;
3116
+ store;
3117
+ async list(guildId, withUserCount) {
3118
+ let url = `/guilds/${guildId}/scheduled-events`;
3119
+ if (withUserCount) url += "?with_user_count=true";
3120
+ const result = await this.rest.get(url);
3121
+ if (!result.ok) return result;
3122
+ const events = result.data.map((e) => {
3123
+ const event = buildScheduledEvent(e);
3124
+ this.store.scheduledEvents.set(event.id, event);
3125
+ return event;
3126
+ });
3127
+ return { ok: true, data: events };
3128
+ }
3129
+ async fetch(guildId, eventId, withUserCount) {
3130
+ const cached = this.store.scheduledEvents.get(eventId);
3131
+ if (cached && !withUserCount) return { ok: true, data: cached };
3132
+ let url = `/guilds/${guildId}/scheduled-events/${eventId}`;
3133
+ if (withUserCount) url += "?with_user_count=true";
3134
+ const result = await this.rest.get(url);
3135
+ if (!result.ok) return result;
3136
+ const event = buildScheduledEvent(result.data);
3137
+ this.store.scheduledEvents.set(event.id, event);
3138
+ return { ok: true, data: event };
2553
3139
  }
2554
- async handleInteraction(raw) {
2555
- const data = raw.data;
2556
- const customId = data.custom_id;
2557
- if (!customId) return;
2558
- const handler = this.handlers.get(customId);
2559
- if (!handler || !handler.execute) return;
2560
- const user = buildUser(raw.user ?? raw.member?.user);
2561
- let guild;
2562
- if (raw.guild_id) {
2563
- guild = this.client.cache.guilds.get(raw.guild_id) ?? { id: raw.guild_id };
2564
- }
2565
- let channel;
2566
- if (raw.channel_id) {
2567
- channel = resolveChannel(raw.channel_id, this.client.cache) ?? { id: raw.channel_id };
2568
- }
2569
- if (data.resolved?.members && data.resolved?.users && raw.guild_id) {
2570
- for (const [id, memberData] of Object.entries(data.resolved.members)) {
2571
- const userData = data.resolved.users[id];
2572
- if (userData) {
2573
- const mergedMember = { ...memberData, user: userData };
2574
- const u = buildUser(userData);
2575
- this.client.cache.users.set(u.id, u);
2576
- }
2577
- }
2578
- }
2579
- const ctx = new ComponentContext2(this.client, raw, user, guild, channel);
2580
- if (handler.type === "user_select" && data.resolved?.users) {
2581
- ctx.values = ctx.values.map((id) => {
2582
- const uData = data.resolved.users[id];
2583
- return uData ? buildUser(uData) : { id };
2584
- });
2585
- } else if (handler.type === "channel_select" && data.resolved?.channels) {
2586
- ctx.values = ctx.values.map((id) => {
2587
- const cData = data.resolved.channels[id];
2588
- return cData ? buildChannel(cData, raw.guild_id) : { id };
2589
- });
2590
- }
2591
- try {
2592
- await handler.execute(ctx);
2593
- } catch (err) {
2594
- console.error(`[COMPONENTS] Error executing component ${customId}:`, err);
3140
+ async create(guildId, payload, reason) {
3141
+ const headers = {};
3142
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
3143
+ const result = await this.rest.post(`/guilds/${guildId}/scheduled-events`, toSnakeCase(payload), headers);
3144
+ if (!result.ok) return result;
3145
+ const event = buildScheduledEvent(result.data);
3146
+ this.store.scheduledEvents.set(event.id, event);
3147
+ return { ok: true, data: event };
3148
+ }
3149
+ async edit(guildId, eventId, payload, reason) {
3150
+ const headers = {};
3151
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
3152
+ const result = await this.rest.patch(`/guilds/${guildId}/scheduled-events/${eventId}`, toSnakeCase(payload), headers);
3153
+ if (!result.ok) return result;
3154
+ const event = buildScheduledEvent(result.data);
3155
+ this.store.scheduledEvents.set(event.id, event);
3156
+ return { ok: true, data: event };
3157
+ }
3158
+ async delete(guildId, eventId) {
3159
+ const result = await this.rest.delete(`/guilds/${guildId}/scheduled-events/${eventId}`);
3160
+ if (result.ok) this.store.scheduledEvents.delete(eventId);
3161
+ return result;
3162
+ }
3163
+ async getUsers(guildId, eventId, options) {
3164
+ let url = `/guilds/${guildId}/scheduled-events/${eventId}/users`;
3165
+ if (options) {
3166
+ const params = new URLSearchParams();
3167
+ if (options.limit) params.append("limit", options.limit.toString());
3168
+ if (options.withMember) params.append("with_member", "true");
3169
+ if (options.before) params.append("before", options.before);
3170
+ if (options.after) params.append("after", options.after);
3171
+ const qs = params.toString();
3172
+ if (qs) url += `?${qs}`;
2595
3173
  }
3174
+ const result = await this.rest.get(url);
3175
+ if (!result.ok) return result;
3176
+ const users = result.data.map((data) => {
3177
+ return {
3178
+ guildScheduledEventId: data.guild_scheduled_event_id,
3179
+ user: buildUser(data.user),
3180
+ member: data.member
3181
+ };
3182
+ });
3183
+ return { ok: true, data: users };
2596
3184
  }
2597
3185
  };
2598
3186
 
2599
- // src/managers/base.ts
2600
- var BaseManager = class {
3187
+ // src/managers/entitlement.ts
3188
+ var EntitlementManager = class {
2601
3189
  constructor(rest, store) {
2602
3190
  this.rest = rest;
2603
3191
  this.store = store;
2604
3192
  }
2605
3193
  rest;
2606
3194
  store;
2607
- async fetch(id, force = false) {
2608
- if (!force) {
2609
- const tongue2 = this.store[this.storeKey];
2610
- const cached = tongue2.get(id);
2611
- if (cached) return { ok: true, data: cached };
3195
+ async list(applicationId, options) {
3196
+ let url = `/applications/${applicationId}/entitlements`;
3197
+ if (options) {
3198
+ const params = new URLSearchParams();
3199
+ if (options.userId) params.append("user_id", options.userId);
3200
+ if (options.skuIds) params.append("sku_ids", options.skuIds.join(","));
3201
+ if (options.before) params.append("before", options.before);
3202
+ if (options.after) params.append("after", options.after);
3203
+ if (options.limit) params.append("limit", options.limit.toString());
3204
+ if (options.guildId) params.append("guild_id", options.guildId);
3205
+ if (options.excludeEnded) params.append("exclude_ended", "true");
3206
+ const qs = params.toString();
3207
+ if (qs) url += `?${qs}`;
2612
3208
  }
2613
- const result = await this.rest.get(this.endpoint(id));
3209
+ const result = await this.rest.get(url);
2614
3210
  if (!result.ok) return result;
2615
- const entity = this.build(result.data);
2616
- const tongue = this.store[this.storeKey];
2617
- tongue.set(id, entity);
2618
- return { ok: true, data: entity };
3211
+ const entitlements = result.data.map((e) => buildEntitlement(e));
3212
+ return { ok: true, data: entitlements };
2619
3213
  }
2620
- };
2621
-
2622
- // src/managers/user.ts
2623
- var UserManager = class extends BaseManager {
2624
- storeKey = "users";
2625
- endpoint(id) {
2626
- return `/users/${id}`;
3214
+ async fetch(applicationId, entitlementId) {
3215
+ const result = await this.rest.get(`/applications/${applicationId}/entitlements/${entitlementId}`);
3216
+ if (!result.ok) return result;
3217
+ return { ok: true, data: buildEntitlement(result.data) };
3218
+ }
3219
+ async createTest(applicationId, payload) {
3220
+ const result = await this.rest.post(`/applications/${applicationId}/entitlements`, toSnakeCase(payload));
3221
+ if (!result.ok) return result;
3222
+ return { ok: true, data: buildEntitlement(result.data) };
3223
+ }
3224
+ async deleteTest(applicationId, entitlementId) {
3225
+ const result = await this.rest.delete(`/applications/${applicationId}/entitlements/${entitlementId}`);
3226
+ return result;
2627
3227
  }
2628
- build = buildUser;
2629
3228
  };
2630
3229
 
2631
- // src/managers/guild.ts
2632
- var GuildManager = class extends BaseManager {
2633
- storeKey = "guilds";
2634
- endpoint(id) {
2635
- return `/guilds/${id}`;
3230
+ // src/managers/stage.ts
3231
+ var StageInstanceManager = class {
3232
+ constructor(rest, store) {
3233
+ this.rest = rest;
3234
+ this.store = store;
2636
3235
  }
2637
- build = buildGuild;
2638
- async fetchChannels(guildId) {
2639
- const result = await this.rest.get(`/guilds/${guildId}/channels`);
3236
+ rest;
3237
+ store;
3238
+ async fetch(channelId) {
3239
+ const cached = Array.from(this.store.stageInstances.values()).find((s) => s.channelId === channelId);
3240
+ if (cached) return { ok: true, data: cached };
3241
+ const result = await this.rest.get(`/stage-instances/${channelId}`);
2640
3242
  if (!result.ok) return result;
2641
- const channels = result.data.map((raw) => buildChannel(raw, guildId));
2642
- for (const c of channels) {
2643
- this.store.channels.set(c.id, c);
2644
- }
2645
- return { ok: true, data: channels };
3243
+ const stage = buildStageInstance(result.data);
3244
+ this.store.stageInstances.set(stage.id, stage);
3245
+ return { ok: true, data: stage };
2646
3246
  }
2647
- async ban(guildId, userId, options) {
2648
- const payload = {};
2649
- if (options?.deleteMessageSeconds !== void 0) payload.delete_message_seconds = options.deleteMessageSeconds;
3247
+ async create(payload, reason) {
2650
3248
  const headers = {};
2651
- if (options?.reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(options.reason);
2652
- const result = await this.rest.put(`/guilds/${guildId}/bans/${userId}`, payload, headers);
2653
- return result;
3249
+ if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
3250
+ const result = await this.rest.post(`/stage-instances`, toSnakeCase(payload), headers);
3251
+ if (!result.ok) return result;
3252
+ const stage = buildStageInstance(result.data);
3253
+ this.store.stageInstances.set(stage.id, stage);
3254
+ return { ok: true, data: stage };
2654
3255
  }
2655
- async unban(guildId, userId, reason) {
3256
+ async edit(channelId, payload, reason) {
2656
3257
  const headers = {};
2657
3258
  if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2658
- const result = await this.rest.delete(`/guilds/${guildId}/bans/${userId}`, headers);
2659
- return result;
3259
+ const result = await this.rest.patch(`/stage-instances/${channelId}`, toSnakeCase(payload), headers);
3260
+ if (!result.ok) return result;
3261
+ const stage = buildStageInstance(result.data);
3262
+ this.store.stageInstances.set(stage.id, stage);
3263
+ return { ok: true, data: stage };
2660
3264
  }
2661
- async kick(guildId, userId, reason) {
3265
+ async delete(channelId, reason) {
2662
3266
  const headers = {};
2663
3267
  if (reason) headers["X-Audit-Log-Reason"] = encodeURIComponent(reason);
2664
- const result = await this.rest.delete(`/guilds/${guildId}/members/${userId}`, headers);
3268
+ const result = await this.rest.delete(`/stage-instances/${channelId}`, headers);
2665
3269
  if (result.ok) {
2666
- this.store.members.delete(TongueStore.memberKey(guildId, userId));
3270
+ const cached = Array.from(this.store.stageInstances.values()).find((s) => s.channelId === channelId);
3271
+ if (cached) this.store.stageInstances.delete(cached.id);
2667
3272
  }
2668
3273
  return result;
2669
3274
  }
2670
3275
  };
2671
3276
 
2672
- // src/managers/channel.ts
2673
- var ChannelManager = class extends BaseManager {
2674
- storeKey = "channels";
2675
- endpoint(id) {
2676
- return `/channels/${id}`;
2677
- }
2678
- build = buildChannel;
2679
- };
2680
-
2681
- // src/managers/member.ts
2682
- var MemberManager = class {
2683
- constructor(rest, store, guildId) {
3277
+ // src/managers/template.ts
3278
+ var TemplateManager = class {
3279
+ constructor(rest) {
2684
3280
  this.rest = rest;
2685
- this.store = store;
2686
- this.guildId = guildId;
2687
3281
  }
2688
3282
  rest;
2689
- store;
2690
- guildId;
2691
- async fetch(userId, force = false) {
2692
- const cacheKey = TongueStore.memberKey(this.guildId, userId);
2693
- if (!force) {
2694
- const cached = this.store.members.get(cacheKey);
2695
- if (cached) return { ok: true, data: cached };
2696
- }
2697
- const result = await this.rest.get(`/guilds/${this.guildId}/members/${userId}`);
3283
+ async fetch(code) {
3284
+ const result = await this.rest.get(`/guilds/templates/${code}`);
2698
3285
  if (!result.ok) return result;
2699
- const member = buildMember(result.data, this.guildId, this.store);
2700
- this.store.members.set(cacheKey, member);
2701
- return { ok: true, data: member };
3286
+ return { ok: true, data: toCamelCase(result.data) };
3287
+ }
3288
+ async createGuildFromTemplate(code, payload) {
3289
+ const result = await this.rest.post(`/guilds/templates/${code}`, toSnakeCase(payload));
3290
+ return result;
3291
+ }
3292
+ async list(guildId) {
3293
+ const result = await this.rest.get(`/guilds/${guildId}/templates`);
3294
+ if (!result.ok) return result;
3295
+ return { ok: true, data: result.data.map((t) => toCamelCase(t)) };
3296
+ }
3297
+ async create(guildId, payload) {
3298
+ const result = await this.rest.post(`/guilds/${guildId}/templates`, toSnakeCase(payload));
3299
+ if (!result.ok) return result;
3300
+ return { ok: true, data: toCamelCase(result.data) };
3301
+ }
3302
+ async sync(guildId, code) {
3303
+ const result = await this.rest.put(`/guilds/${guildId}/templates/${code}`);
3304
+ if (!result.ok) return result;
3305
+ return { ok: true, data: toCamelCase(result.data) };
3306
+ }
3307
+ async edit(guildId, code, payload) {
3308
+ const result = await this.rest.patch(`/guilds/${guildId}/templates/${code}`, toSnakeCase(payload));
3309
+ if (!result.ok) return result;
3310
+ return { ok: true, data: toCamelCase(result.data) };
3311
+ }
3312
+ async delete(guildId, code) {
3313
+ const result = await this.rest.delete(`/guilds/${guildId}/templates/${code}`);
3314
+ if (!result.ok) return result;
3315
+ return { ok: true, data: toCamelCase(result.data) };
2702
3316
  }
2703
3317
  };
2704
3318
 
2705
- // src/managers/message.ts
2706
- var MessageManager = class {
2707
- constructor(rest, store) {
3319
+ // src/managers/application.ts
3320
+ var ApplicationManager = class {
3321
+ constructor(rest, _client) {
2708
3322
  this.rest = rest;
2709
- this.store = store;
3323
+ this._client = _client;
2710
3324
  }
2711
3325
  rest;
2712
- store;
2713
- async fetch(channelId, messageId, force = false) {
2714
- if (!force) {
2715
- const cached = this.store.messages.get(messageId);
2716
- if (cached) return { ok: true, data: cached };
2717
- }
2718
- const result = await this.rest.get(`/channels/${channelId}/messages/${messageId}`);
3326
+ _client;
3327
+ async fetch() {
3328
+ const result = await this.rest.get("/oauth2/applications/@me");
2719
3329
  if (!result.ok) return result;
2720
- const message = buildMessage(result.data, this.store);
2721
- this.store.messages.set(message.id, message);
2722
- return { ok: true, data: message };
3330
+ return { ok: true, data: result.data };
2723
3331
  }
2724
- async send(channelId, payload) {
2725
- const data = typeof payload === "string" ? { content: payload } : payload;
2726
- const result = await this.rest.post(`/channels/${channelId}/messages`, data);
3332
+ async fetchRoleConnectionMetadata() {
3333
+ if (!this._client.user?.id) {
3334
+ return { ok: false, status: 400, message: "Client not ready" };
3335
+ }
3336
+ const result = await this.rest.get(`/applications/${this._client.user.id}/role-connections/metadata`);
2727
3337
  if (!result.ok) return result;
2728
- const message = buildMessage(result.data, this.store);
2729
- this.store.messages.set(message.id, message);
2730
- return { ok: true, data: message };
3338
+ return { ok: true, data: result.data };
2731
3339
  }
2732
- async edit(channelId, messageId, payload) {
2733
- const data = typeof payload === "string" ? { content: payload } : payload;
2734
- const result = await this.rest.patch(`/channels/${channelId}/messages/${messageId}`, data);
3340
+ async editRoleConnectionMetadata(records) {
3341
+ if (!this._client.user?.id) {
3342
+ return { ok: false, status: 400, message: "Client not ready" };
3343
+ }
3344
+ const result = await this.rest.put(`/applications/${this._client.user.id}/role-connections/metadata`, records);
2735
3345
  if (!result.ok) return result;
2736
- const oldMsg = this.store.messages.get(messageId);
2737
- const message = buildMessage(result.data, this.store, oldMsg);
2738
- this.store.messages.set(message.id, message);
2739
- return { ok: true, data: message };
3346
+ return { ok: true, data: result.data };
2740
3347
  }
2741
- async delete(channelId, messageId) {
2742
- const result = await this.rest.delete(`/channels/${channelId}/messages/${messageId}`);
2743
- if (result.ok) {
2744
- this.store.messages.delete(messageId);
3348
+ };
3349
+
3350
+ // src/builders/attachment.ts
3351
+ import * as fs2 from "fs";
3352
+ import * as path2 from "path";
3353
+ var AttachmentBuilder = class {
3354
+ name;
3355
+ data;
3356
+ description;
3357
+ contentType;
3358
+ constructor(data, options) {
3359
+ if (typeof data === "string") {
3360
+ const resolved = path2.resolve(data);
3361
+ this.data = fs2.readFileSync(resolved);
3362
+ this.name = options?.name ?? path2.basename(resolved);
3363
+ } else {
3364
+ this.data = data;
3365
+ this.name = options?.name ?? "file.bin";
2745
3366
  }
2746
- return result;
3367
+ if (options?.description !== void 0) this.description = options.description;
3368
+ if (options?.contentType !== void 0) this.contentType = options.contentType;
3369
+ }
3370
+ setName(name) {
3371
+ this.name = name;
3372
+ return this;
3373
+ }
3374
+ setDescription(description) {
3375
+ this.description = description;
3376
+ return this;
3377
+ }
3378
+ toAttachmentJSON(index) {
3379
+ return {
3380
+ id: index,
3381
+ filename: this.name,
3382
+ ...this.description ? { description: this.description } : {}
3383
+ };
2747
3384
  }
2748
3385
  };
2749
3386
 
2750
- // src/managers/collector.ts
2751
- var CollectorManager = class {
2752
- constructor(client) {
2753
- this.client = client;
3387
+ // src/managers/soundboard.ts
3388
+ var SoundboardManager = class {
3389
+ constructor(rest) {
3390
+ this.rest = rest;
2754
3391
  }
2755
- client;
2756
- /**
2757
- * Waits for a specified number of messages in a given channel that pass the filter, if the time limit
2758
- * is reached, resolves with the messages collected so far
2759
- */
2760
- async awaitMessages(channelId, options = {}) {
2761
- const { filter, max = 1, time = 15e3 } = options;
2762
- return new Promise((resolve2) => {
2763
- const messages = [];
2764
- let timeoutId = null;
2765
- const handler = (data) => {
2766
- const msg = data.message;
2767
- if (msg.channelId !== channelId) return;
2768
- if (filter && !filter(msg)) return;
2769
- messages.push(msg);
2770
- if (messages.length >= max) {
2771
- cleanup();
2772
- resolve2(messages);
2773
- }
2774
- };
2775
- const cleanup = () => {
2776
- if (timeoutId) clearTimeout(timeoutId);
2777
- this.client.off("MESSAGE_CREATE", handler);
2778
- };
2779
- this.client.on("MESSAGE_CREATE", handler);
2780
- if (time > 0) {
2781
- timeoutId = setTimeout(() => {
2782
- cleanup();
2783
- resolve2(messages);
2784
- }, time);
2785
- }
2786
- });
3392
+ rest;
3393
+ async send(channelId, soundId, sourceGuildId) {
3394
+ const payload = {
3395
+ sound_id: soundId
3396
+ };
3397
+ if (sourceGuildId !== void 0) payload.source_guild_id = sourceGuildId;
3398
+ const result = await this.rest.post(`/channels/${channelId}/send-soundboard-sound`, payload);
3399
+ return result;
2787
3400
  }
2788
- /**
2789
- * waits for a single component interaction on a specific message,
2790
- * resolves with the ComponentContext if successful, or null if it timed out
2791
- */
2792
- async awaitComponent(messageId, options = {}) {
2793
- const { filter, time = 15e3 } = options;
2794
- return new Promise((resolve2) => {
2795
- let timeoutId = null;
2796
- const handler = (data) => {
2797
- const raw = data.interaction;
2798
- if (raw.type !== 3 /* MESSAGE_COMPONENT */) return;
2799
- if (raw.message?.id !== messageId) return;
2800
- const userRaw = raw.member?.user || raw.user;
2801
- const user = buildUser(userRaw);
2802
- const ctx = new ComponentContext(
2803
- this.client,
2804
- raw,
2805
- user,
2806
- raw.guild_id ? resolveGuild(raw.guild_id, this.client.cache) : void 0,
2807
- raw.channel_id ? resolveChannel(raw.channel_id, this.client.cache) : void 0
2808
- );
2809
- if (raw.data.component_type === 3 /* STRING_SELECT */ || raw.data.component_type === 5 /* USER_SELECT */ || raw.data.component_type === 6 /* ROLE_SELECT */ || raw.data.component_type === 7 /* MENTIONABLE_SELECT */ || raw.data.component_type === 8 /* CHANNEL_SELECT */) {
2810
- ctx._values = raw.data.values || [];
2811
- }
2812
- if (filter && !filter(ctx)) return;
2813
- cleanup();
2814
- resolve2(ctx);
2815
- };
2816
- const cleanup = () => {
2817
- if (timeoutId) clearTimeout(timeoutId);
2818
- this.client.off("INTERACTION_CREATE", handler);
2819
- };
2820
- this.client.on("INTERACTION_CREATE", handler);
2821
- if (time > 0) {
2822
- timeoutId = setTimeout(() => {
2823
- cleanup();
2824
- resolve2(null);
2825
- }, time);
2826
- }
2827
- });
3401
+ async fetchDefault() {
3402
+ const result = await this.rest.get("/soundboard-default-sounds");
3403
+ if (!result.ok) return result;
3404
+ return { ok: true, data: result.data };
3405
+ }
3406
+ async fetch(guildId, soundId) {
3407
+ if (soundId) {
3408
+ const result = await this.rest.get(`/guilds/${guildId}/soundboard-sounds/${soundId}`);
3409
+ if (!result.ok) return result;
3410
+ return { ok: true, data: result.data };
3411
+ } else {
3412
+ const result = await this.rest.get(`/guilds/${guildId}/soundboard-sounds`);
3413
+ if (!result.ok) return result;
3414
+ return { ok: true, data: result.data.items };
3415
+ }
3416
+ }
3417
+ async create(guildId, options, reason) {
3418
+ let soundData = options.sound;
3419
+ if (options.sound instanceof AttachmentBuilder) {
3420
+ soundData = `data:${options.sound.contentType ?? "audio/ogg"};base64,${Buffer.from(options.sound.data).toString("base64")}`;
3421
+ }
3422
+ const payload = {
3423
+ name: options.name,
3424
+ sound: soundData
3425
+ };
3426
+ if (options.volume !== void 0) payload.volume = options.volume;
3427
+ if (options.emojiId !== void 0) payload.emoji_id = options.emojiId;
3428
+ if (options.emojiName !== void 0) payload.emoji_name = options.emojiName;
3429
+ const headers = {};
3430
+ if (reason) headers["X-Audit-Log-Reason"] = reason;
3431
+ const result = await this.rest.post(`/guilds/${guildId}/soundboard-sounds`, payload, headers);
3432
+ if (!result.ok) return result;
3433
+ return { ok: true, data: result.data };
3434
+ }
3435
+ async edit(guildId, soundId, options, reason) {
3436
+ const payload = {};
3437
+ if (options.name !== void 0) payload.name = options.name;
3438
+ if (options.volume !== void 0) payload.volume = options.volume;
3439
+ if (options.emojiId !== void 0) payload.emoji_id = options.emojiId;
3440
+ if (options.emojiName !== void 0) payload.emoji_name = options.emojiName;
3441
+ const headers = {};
3442
+ if (reason) headers["X-Audit-Log-Reason"] = reason;
3443
+ const result = await this.rest.patch(`/guilds/${guildId}/soundboard-sounds/${soundId}`, payload, headers);
3444
+ if (!result.ok) return result;
3445
+ return { ok: true, data: result.data };
3446
+ }
3447
+ async delete(guildId, soundId, reason) {
3448
+ const headers = {};
3449
+ if (reason) headers["X-Audit-Log-Reason"] = reason;
3450
+ const result = await this.rest.delete(`/guilds/${guildId}/soundboard-sounds/${soundId}`, headers);
3451
+ return result;
2828
3452
  }
2829
3453
  };
2830
3454
 
@@ -2849,6 +3473,15 @@ var Client = class {
2849
3473
  channels;
2850
3474
  messages;
2851
3475
  collectors;
3476
+ webhooks;
3477
+ invites;
3478
+ autoMod;
3479
+ scheduledEvents;
3480
+ entitlements;
3481
+ stageInstances;
3482
+ templates;
3483
+ application;
3484
+ soundboard;
2852
3485
  listeners = /* @__PURE__ */ new Map();
2853
3486
  middlewares = [];
2854
3487
  constructor(options) {
@@ -2865,6 +3498,16 @@ var Client = class {
2865
3498
  this.channels = new ChannelManager(this.rest, this.cache);
2866
3499
  this.messages = new MessageManager(this.rest, this.cache);
2867
3500
  this.collectors = new CollectorManager(this);
3501
+ this.webhooks = new WebhookManager(this.rest, this.cache);
3502
+ this.invites = new InviteManager(this.rest);
3503
+ this.autoMod = new AutoModerationManager(this.rest, this.cache);
3504
+ this.scheduledEvents = new ScheduledEventManager(this.rest, this.cache);
3505
+ this.entitlements = new EntitlementManager(this.rest, this.cache);
3506
+ this.stageInstances = new StageInstanceManager(this.rest, this.cache);
3507
+ this.templates = new TemplateManager(this.rest);
3508
+ this.application = new ApplicationManager(this.rest, this);
3509
+ this.soundboard = new SoundboardManager(this.rest);
3510
+ this.gateway = new ChameleonGateway({ token: this.token, intents: this.intents });
2868
3511
  let shards = [0];
2869
3512
  let totalShards = 1;
2870
3513
  if (options.sharding === "auto") {
@@ -3079,22 +3722,26 @@ var Client = class {
3079
3722
  }
3080
3723
  if (Array.isArray(d.emojis)) {
3081
3724
  for (const raw of d.emojis) {
3082
- this.cache.emojis.set(raw.id, raw);
3725
+ const emoji = buildEmoji(raw);
3726
+ if (emoji.id) this.cache.emojis.set(emoji.id, emoji);
3083
3727
  }
3084
3728
  }
3085
3729
  if (Array.isArray(d.stickers)) {
3086
3730
  for (const raw of d.stickers) {
3087
- this.cache.stickers.set(raw.id, raw);
3731
+ const sticker = buildSticker(raw);
3732
+ this.cache.stickers.set(sticker.id, sticker);
3088
3733
  }
3089
3734
  }
3090
3735
  if (Array.isArray(d.stage_instances)) {
3091
3736
  for (const raw of d.stage_instances) {
3092
- this.cache.stageInstances.set(raw.id, raw);
3737
+ const stage = buildStageInstance(raw);
3738
+ this.cache.stageInstances.set(stage.id, stage);
3093
3739
  }
3094
3740
  }
3095
3741
  if (Array.isArray(d.guild_scheduled_events)) {
3096
3742
  for (const raw of d.guild_scheduled_events) {
3097
- this.cache.scheduledEvents.set(raw.id, raw);
3743
+ const event = buildScheduledEvent(raw);
3744
+ this.cache.scheduledEvents.set(event.id, event);
3098
3745
  }
3099
3746
  }
3100
3747
  if (guild.large) {
@@ -3279,7 +3926,7 @@ var Client = class {
3279
3926
  this.dispatch("MESSAGE_CREATE", {
3280
3927
  type: "MESSAGE_CREATE",
3281
3928
  message,
3282
- channel: resolveChannel(message.channelId, this.cache)
3929
+ channel: resolveChannel(message.channelId, this)
3283
3930
  });
3284
3931
  break;
3285
3932
  }
@@ -3290,7 +3937,7 @@ var Client = class {
3290
3937
  this.dispatch("MESSAGE_UPDATE", {
3291
3938
  type: "MESSAGE_UPDATE",
3292
3939
  message,
3293
- channel: resolveChannel(message.channelId, this.cache),
3940
+ channel: resolveChannel(message.channelId, this),
3294
3941
  ...oldMessage ? { oldMessage } : {}
3295
3942
  });
3296
3943
  break;
@@ -3383,14 +4030,25 @@ var Client = class {
3383
4030
  }
3384
4031
  this.dispatch("INTERACTION_CREATE", {
3385
4032
  type: "INTERACTION_CREATE",
3386
- interaction: d
4033
+ interaction: buildInteraction(d, this.cache)
3387
4034
  });
3388
4035
  break;
3389
4036
  }
3390
4037
  case "VOICE_STATE_UPDATE": {
4038
+ const guildId = d.guild_id;
4039
+ const userId = d.user_id;
4040
+ const key = guildId ? TongueStore.memberKey(guildId, userId) : userId;
4041
+ const oldVoiceState = this.cache.voiceStates.get(key);
4042
+ const voiceState = buildVoiceState(d, this.cache);
4043
+ if (!d.channel_id) {
4044
+ this.cache.voiceStates.delete(key);
4045
+ } else {
4046
+ this.cache.voiceStates.set(key, voiceState);
4047
+ }
3391
4048
  this.dispatch("VOICE_STATE_UPDATE", {
3392
4049
  type: "VOICE_STATE_UPDATE",
3393
- voiceState: d
4050
+ voiceState,
4051
+ ...oldVoiceState ? { oldVoiceState } : {}
3394
4052
  });
3395
4053
  break;
3396
4054
  }
@@ -3438,15 +4096,15 @@ var Client = class {
3438
4096
  break;
3439
4097
  }
3440
4098
  case "ENTITLEMENT_CREATE": {
3441
- this.dispatch("ENTITLEMENT_CREATE", { type: "ENTITLEMENT_CREATE", entitlement: d });
4099
+ this.dispatch("ENTITLEMENT_CREATE", { type: "ENTITLEMENT_CREATE", entitlement: buildEntitlement(d) });
3442
4100
  break;
3443
4101
  }
3444
4102
  case "ENTITLEMENT_UPDATE": {
3445
- this.dispatch("ENTITLEMENT_UPDATE", { type: "ENTITLEMENT_UPDATE", entitlement: d });
4103
+ this.dispatch("ENTITLEMENT_UPDATE", { type: "ENTITLEMENT_UPDATE", entitlement: buildEntitlement(d) });
3446
4104
  break;
3447
4105
  }
3448
4106
  case "ENTITLEMENT_DELETE": {
3449
- this.dispatch("ENTITLEMENT_DELETE", { type: "ENTITLEMENT_DELETE", entitlement: d });
4107
+ this.dispatch("ENTITLEMENT_DELETE", { type: "ENTITLEMENT_DELETE", entitlement: buildEntitlement(d) });
3450
4108
  break;
3451
4109
  }
3452
4110
  case "PRESENCE_UPDATE": {
@@ -3578,7 +4236,7 @@ var Client = class {
3578
4236
  break;
3579
4237
  }
3580
4238
  case "GUILD_EMOJIS_UPDATE": {
3581
- const emojis = d.emojis;
4239
+ const emojis = d.emojis.map((raw) => buildEmoji(raw));
3582
4240
  for (const emoji of emojis) {
3583
4241
  if (emoji.id) this.cache.emojis.set(emoji.id, emoji);
3584
4242
  }
@@ -3590,7 +4248,7 @@ var Client = class {
3590
4248
  break;
3591
4249
  }
3592
4250
  case "GUILD_STICKERS_UPDATE": {
3593
- const stickers = d.stickers;
4251
+ const stickers = d.stickers.map((raw) => buildSticker(raw));
3594
4252
  for (const sticker of stickers) {
3595
4253
  this.cache.stickers.set(sticker.id, sticker);
3596
4254
  }
@@ -3602,37 +4260,37 @@ var Client = class {
3602
4260
  break;
3603
4261
  }
3604
4262
  case "STAGE_INSTANCE_CREATE": {
3605
- const stageInstance = d;
4263
+ const stageInstance = buildStageInstance(d);
3606
4264
  this.cache.stageInstances.set(stageInstance.id, stageInstance);
3607
4265
  this.dispatch("STAGE_INSTANCE_CREATE", { type: "STAGE_INSTANCE_CREATE", stageInstance });
3608
4266
  break;
3609
4267
  }
3610
4268
  case "STAGE_INSTANCE_UPDATE": {
3611
- const stageInstance = d;
4269
+ const stageInstance = buildStageInstance(d);
3612
4270
  this.cache.stageInstances.set(stageInstance.id, stageInstance);
3613
4271
  this.dispatch("STAGE_INSTANCE_UPDATE", { type: "STAGE_INSTANCE_UPDATE", stageInstance });
3614
4272
  break;
3615
4273
  }
3616
4274
  case "STAGE_INSTANCE_DELETE": {
3617
- const stageInstance = d;
4275
+ const stageInstance = buildStageInstance(d);
3618
4276
  this.cache.stageInstances.delete(stageInstance.id);
3619
4277
  this.dispatch("STAGE_INSTANCE_DELETE", { type: "STAGE_INSTANCE_DELETE", stageInstance });
3620
4278
  break;
3621
4279
  }
3622
4280
  case "GUILD_SCHEDULED_EVENT_CREATE": {
3623
- const scheduledEvent = d;
4281
+ const scheduledEvent = buildScheduledEvent(d);
3624
4282
  this.cache.scheduledEvents.set(scheduledEvent.id, scheduledEvent);
3625
4283
  this.dispatch("GUILD_SCHEDULED_EVENT_CREATE", { type: "GUILD_SCHEDULED_EVENT_CREATE", scheduledEvent });
3626
4284
  break;
3627
4285
  }
3628
4286
  case "GUILD_SCHEDULED_EVENT_UPDATE": {
3629
- const scheduledEvent = d;
4287
+ const scheduledEvent = buildScheduledEvent(d);
3630
4288
  this.cache.scheduledEvents.set(scheduledEvent.id, scheduledEvent);
3631
4289
  this.dispatch("GUILD_SCHEDULED_EVENT_UPDATE", { type: "GUILD_SCHEDULED_EVENT_UPDATE", scheduledEvent });
3632
4290
  break;
3633
4291
  }
3634
4292
  case "GUILD_SCHEDULED_EVENT_DELETE": {
3635
- const scheduledEvent = d;
4293
+ const scheduledEvent = buildScheduledEvent(d);
3636
4294
  this.cache.scheduledEvents.delete(scheduledEvent.id);
3637
4295
  this.dispatch("GUILD_SCHEDULED_EVENT_DELETE", { type: "GUILD_SCHEDULED_EVENT_DELETE", scheduledEvent });
3638
4296
  break;
@@ -3646,19 +4304,19 @@ var Client = class {
3646
4304
  break;
3647
4305
  }
3648
4306
  case "AUTO_MODERATION_RULE_CREATE": {
3649
- const rule = d;
4307
+ const rule = buildAutoModRule(d);
3650
4308
  this.cache.autoModRules.set(rule.id, rule);
3651
4309
  this.dispatch("AUTO_MODERATION_RULE_CREATE", { type: "AUTO_MODERATION_RULE_CREATE", rule });
3652
4310
  break;
3653
4311
  }
3654
4312
  case "AUTO_MODERATION_RULE_UPDATE": {
3655
- const rule = d;
4313
+ const rule = buildAutoModRule(d);
3656
4314
  this.cache.autoModRules.set(rule.id, rule);
3657
4315
  this.dispatch("AUTO_MODERATION_RULE_UPDATE", { type: "AUTO_MODERATION_RULE_UPDATE", rule });
3658
4316
  break;
3659
4317
  }
3660
4318
  case "AUTO_MODERATION_RULE_DELETE": {
3661
- const rule = d;
4319
+ const rule = buildAutoModRule(d);
3662
4320
  this.cache.autoModRules.delete(rule.id);
3663
4321
  this.dispatch("AUTO_MODERATION_RULE_DELETE", { type: "AUTO_MODERATION_RULE_DELETE", rule });
3664
4322
  break;
@@ -3680,13 +4338,13 @@ var Client = class {
3680
4338
  break;
3681
4339
  }
3682
4340
  case "INTEGRATION_CREATE": {
3683
- const integration = d;
4341
+ const integration = buildIntegration(d);
3684
4342
  this.cache.integrations.set(integration.id, integration);
3685
4343
  this.dispatch("INTEGRATION_CREATE", { type: "INTEGRATION_CREATE", guildId: d.guild_id, integration });
3686
4344
  break;
3687
4345
  }
3688
4346
  case "INTEGRATION_UPDATE": {
3689
- const integration = d;
4347
+ const integration = buildIntegration(d);
3690
4348
  this.cache.integrations.set(integration.id, integration);
3691
4349
  this.dispatch("INTEGRATION_UPDATE", { type: "INTEGRATION_UPDATE", guildId: d.guild_id, integration });
3692
4350
  break;
@@ -3752,6 +4410,301 @@ var Chameleon = class {
3752
4410
  };
3753
4411
  }
3754
4412
  };
4413
+
4414
+ // src/utils/bitfield.ts
4415
+ var BitField = class _BitField {
4416
+ static FLAGS = {};
4417
+ bitfield;
4418
+ constructor(bits = 0n) {
4419
+ this.bitfield = this.constructor.resolve(bits);
4420
+ }
4421
+ has(bit) {
4422
+ const resolved = this.constructor.resolve(bit);
4423
+ return (this.bitfield & resolved) === resolved;
4424
+ }
4425
+ any(bit) {
4426
+ const resolved = this.constructor.resolve(bit);
4427
+ return (this.bitfield & resolved) !== 0n;
4428
+ }
4429
+ add(...bits) {
4430
+ let total = 0n;
4431
+ for (const bit of bits) {
4432
+ total |= this.constructor.resolve(bit);
4433
+ }
4434
+ this.bitfield |= total;
4435
+ return this;
4436
+ }
4437
+ remove(...bits) {
4438
+ let total = 0n;
4439
+ for (const bit of bits) {
4440
+ total |= this.constructor.resolve(bit);
4441
+ }
4442
+ this.bitfield &= ~total;
4443
+ return this;
4444
+ }
4445
+ toArray() {
4446
+ const flags = this.constructor.FLAGS;
4447
+ return Object.keys(flags).filter((flag) => this.has(flags[flag]));
4448
+ }
4449
+ serialize() {
4450
+ const flags = this.constructor.FLAGS;
4451
+ const result = {};
4452
+ for (const [flag, value] of Object.entries(flags)) {
4453
+ result[flag] = this.has(value);
4454
+ }
4455
+ return result;
4456
+ }
4457
+ equals(other) {
4458
+ return this.bitfield === this.constructor.resolve(other);
4459
+ }
4460
+ freeze() {
4461
+ return Object.freeze(this);
4462
+ }
4463
+ toString() {
4464
+ return this.bitfield.toString();
4465
+ }
4466
+ toJSON() {
4467
+ return this.toString();
4468
+ }
4469
+ static resolve(bit) {
4470
+ if (typeof bit === "bigint") return bit;
4471
+ if (typeof bit === "number") return BigInt(bit);
4472
+ if (bit instanceof _BitField) return bit.bitfield;
4473
+ if (typeof bit === "string") {
4474
+ const flag = this.FLAGS[bit];
4475
+ if (flag !== void 0) return flag;
4476
+ const parsed = BigInt(bit);
4477
+ return parsed;
4478
+ }
4479
+ if (Array.isArray(bit)) {
4480
+ return bit.reduce((acc, b) => acc | this.resolve(b), 0n);
4481
+ }
4482
+ throw new TypeError(`Cannot resolve BitField from: ${bit}`);
4483
+ }
4484
+ };
4485
+
4486
+ // src/types/permissions.ts
4487
+ var PermissionsBitField = class _PermissionsBitField extends BitField {
4488
+ static FLAGS = { ...DISCORD_PERMISSIONS };
4489
+ static ALL = Object.values(DISCORD_PERMISSIONS).reduce((a, b) => a | b, 0n);
4490
+ get isAdmin() {
4491
+ return this.has("ADMINISTRATOR");
4492
+ }
4493
+ static from(bits) {
4494
+ return new _PermissionsBitField(bits);
4495
+ }
4496
+ };
4497
+ var UserFlagsBitField = class extends BitField {
4498
+ static FLAGS = {
4499
+ STAFF: 1n << 0n,
4500
+ PARTNER: 1n << 1n,
4501
+ HYPESQUAD: 1n << 2n,
4502
+ BUG_HUNTER_LEVEL_1: 1n << 3n,
4503
+ HYPESQUAD_ONLINE_HOUSE_1: 1n << 6n,
4504
+ HYPESQUAD_ONLINE_HOUSE_2: 1n << 7n,
4505
+ HYPESQUAD_ONLINE_HOUSE_3: 1n << 8n,
4506
+ PREMIUM_EARLY_SUPPORTER: 1n << 9n,
4507
+ TEAM_PSEUDO_USER: 1n << 10n,
4508
+ BUG_HUNTER_LEVEL_2: 1n << 14n,
4509
+ VERIFIED_BOT: 1n << 16n,
4510
+ VERIFIED_DEVELOPER: 1n << 17n,
4511
+ CERTIFIED_MODERATOR: 1n << 18n,
4512
+ BOT_HTTP_INTERACTIONS: 1n << 19n,
4513
+ ACTIVE_DEVELOPER: 1n << 22n
4514
+ };
4515
+ };
4516
+ var IntentsBitField = class extends BitField {
4517
+ static FLAGS = {
4518
+ Guilds: 1n << 0n,
4519
+ GuildMembers: 1n << 1n,
4520
+ GuildModeration: 1n << 2n,
4521
+ GuildEmojisAndStickers: 1n << 3n,
4522
+ GuildIntegrations: 1n << 4n,
4523
+ GuildWebhooks: 1n << 5n,
4524
+ GuildInvites: 1n << 6n,
4525
+ GuildVoiceStates: 1n << 7n,
4526
+ GuildPresences: 1n << 8n,
4527
+ GuildMessages: 1n << 9n,
4528
+ GuildMessageReactions: 1n << 10n,
4529
+ GuildMessageTyping: 1n << 11n,
4530
+ DirectMessages: 1n << 12n,
4531
+ DirectMessageReactions: 1n << 13n,
4532
+ DirectMessageTyping: 1n << 14n,
4533
+ MessageContent: 1n << 15n,
4534
+ GuildScheduledEvents: 1n << 16n,
4535
+ AutoModerationConfiguration: 1n << 20n,
4536
+ AutoModerationExecution: 1n << 21n,
4537
+ GuildMessagePolls: 1n << 24n,
4538
+ DirectMessagePolls: 1n << 25n
4539
+ };
4540
+ };
4541
+ function computeBasePermissions(member, guild) {
4542
+ if (member.roles === void 0) return 0n;
4543
+ const userId = member.user?.id;
4544
+ if (userId && userId === guild.ownerId) return PermissionsBitField.ALL;
4545
+ const everyoneRole = guild.roles.find((r) => r.id === guild.id);
4546
+ let permissions = everyoneRole ? BigInt(everyoneRole.permissions) : 0n;
4547
+ for (const roleId of member.roles) {
4548
+ const role = guild.roles.find((r) => r.id === roleId);
4549
+ if (role) permissions |= BigInt(role.permissions);
4550
+ }
4551
+ if ((permissions & DISCORD_PERMISSIONS.ADMINISTRATOR) === DISCORD_PERMISSIONS.ADMINISTRATOR) {
4552
+ return PermissionsBitField.ALL;
4553
+ }
4554
+ return permissions;
4555
+ }
4556
+ function computeChannelPermissions(basePermissions, overwrites, memberRoles, memberId) {
4557
+ if ((basePermissions & DISCORD_PERMISSIONS.ADMINISTRATOR) === DISCORD_PERMISSIONS.ADMINISTRATOR) {
4558
+ return PermissionsBitField.ALL;
4559
+ }
4560
+ let permissions = basePermissions;
4561
+ let allow = 0n;
4562
+ let deny = 0n;
4563
+ for (const overwrite of overwrites) {
4564
+ if (overwrite.type === 0) {
4565
+ if (memberRoles.includes(overwrite.id) || overwrites.indexOf(overwrite) === 0) {
4566
+ if (overwrites.indexOf(overwrite) === 0 && !memberRoles.includes(overwrite.id)) {
4567
+ permissions &= ~BigInt(overwrite.deny);
4568
+ permissions |= BigInt(overwrite.allow);
4569
+ } else {
4570
+ allow |= BigInt(overwrite.allow);
4571
+ deny |= BigInt(overwrite.deny);
4572
+ }
4573
+ }
4574
+ }
4575
+ }
4576
+ permissions &= ~deny;
4577
+ permissions |= allow;
4578
+ if (memberId) {
4579
+ const memberOverwrite = overwrites.find((ow) => ow.type === 1 && ow.id === memberId);
4580
+ if (memberOverwrite) {
4581
+ permissions &= ~BigInt(memberOverwrite.deny);
4582
+ permissions |= BigInt(memberOverwrite.allow);
4583
+ }
4584
+ }
4585
+ return permissions;
4586
+ }
4587
+
4588
+ // src/sharding/manager.ts
4589
+ import { EventEmitter } from "events";
4590
+ import { fork } from "child_process";
4591
+ import * as path3 from "path";
4592
+ var Shard = class extends EventEmitter {
4593
+ id;
4594
+ manager;
4595
+ process = null;
4596
+ ready = false;
4597
+ constructor(manager, id) {
4598
+ super();
4599
+ this.manager = manager;
4600
+ this.id = id;
4601
+ }
4602
+ spawn() {
4603
+ return new Promise((resolve4, reject) => {
4604
+ const env = {
4605
+ ...process.env,
4606
+ SHARD_ID: this.id.toString(),
4607
+ SHARD_COUNT: this.manager.totalShards.toString(),
4608
+ DISCORD_TOKEN: this.manager.token
4609
+ };
4610
+ this.process = fork(this.manager.file, [], {
4611
+ env
4612
+ });
4613
+ this.process.on("message", (message) => {
4614
+ this.emit("message", message);
4615
+ this.manager.emit("message", this, message);
4616
+ if (message?.type === "ready") {
4617
+ this.ready = true;
4618
+ this.emit("ready");
4619
+ resolve4(this.process);
4620
+ }
4621
+ });
4622
+ this.process.on("exit", (code, signal) => {
4623
+ this.emit("death", this.process);
4624
+ this.manager.emit("shardDeath", this);
4625
+ this.process = null;
4626
+ this.ready = false;
4627
+ if (this.manager.respawn) {
4628
+ console.warn(`[C-Shard] Shard ${this.id} exited with code ${code} (signal: ${signal})`);
4629
+ setTimeout(() => this.spawn().catch(console.error), 5e3);
4630
+ }
4631
+ });
4632
+ this.process.on("error", (err) => {
4633
+ reject(err);
4634
+ });
4635
+ setTimeout(() => {
4636
+ if (!this.ready) {
4637
+ this.ready = true;
4638
+ this.emit("ready");
4639
+ resolve4(this.process);
4640
+ }
4641
+ }, 3e4);
4642
+ });
4643
+ }
4644
+ send(message) {
4645
+ return new Promise((resolve4, reject) => {
4646
+ if (!this.process) return reject(new Error("Shard is not running"));
4647
+ this.process.send(message, (err) => {
4648
+ if (err) reject(err);
4649
+ else resolve4();
4650
+ });
4651
+ });
4652
+ }
4653
+ kill() {
4654
+ if (this.process) {
4655
+ this.process.removeAllListeners();
4656
+ this.process.kill();
4657
+ this.process = null;
4658
+ this.ready = false;
4659
+ }
4660
+ }
4661
+ };
4662
+ var CShard = class extends EventEmitter {
4663
+ file;
4664
+ totalShards;
4665
+ token;
4666
+ shards = /* @__PURE__ */ new Map();
4667
+ respawn;
4668
+ constructor(file, options) {
4669
+ super();
4670
+ this.file = path3.resolve(file);
4671
+ this.token = options.token;
4672
+ this.totalShards = typeof options.totalShards === "number" ? options.totalShards : 1;
4673
+ this.respawn = options.respawn ?? true;
4674
+ if (options.totalShards === "auto") {
4675
+ this.totalShards = -1;
4676
+ }
4677
+ }
4678
+ async fetchRecommendedShards() {
4679
+ const rest = new ChameleonREST({ token: this.token });
4680
+ const result = await rest.get("/gateway/bot");
4681
+ if (result.ok && result.data && typeof result.data.shards === "number") {
4682
+ return result.data.shards;
4683
+ }
4684
+ console.warn("[Chameleon Sharding] Failed to fetch recommended shards from Discord API. Falling back to 1.");
4685
+ return 1;
4686
+ }
4687
+ async spawn() {
4688
+ if (this.totalShards === -1) {
4689
+ this.totalShards = await this.fetchRecommendedShards();
4690
+ }
4691
+ for (let i = 0; i < this.totalShards; i++) {
4692
+ const shard = new Shard(this, i);
4693
+ this.shards.set(i, shard);
4694
+ this.emit("shardCreate", shard);
4695
+ await shard.spawn();
4696
+ await new Promise((r) => setTimeout(r, 5e3));
4697
+ }
4698
+ return this.shards;
4699
+ }
4700
+ async broadcast(message) {
4701
+ const promises = [];
4702
+ for (const shard of this.shards.values()) {
4703
+ promises.push(shard.send(message));
4704
+ }
4705
+ return Promise.all(promises);
4706
+ }
4707
+ };
3755
4708
  export {
3756
4709
  AUDIT_LOG_EVENT_TYPES,
3757
4710
  ActionRow,
@@ -3763,16 +4716,22 @@ export {
3763
4716
  ApplicationEventWebhookStatus,
3764
4717
  ApplicationFlag,
3765
4718
  ApplicationIntegrationType,
4719
+ ApplicationManager,
3766
4720
  ApplicationRoleConnectionMetadataType,
4721
+ AttachmentBuilder,
3767
4722
  AttachmentFlag,
3768
4723
  AutoModerationActionType,
3769
4724
  AutoModerationEventType,
3770
4725
  AutoModerationKeywordPresetType,
4726
+ AutoModerationManager,
3771
4727
  AutoModerationTriggerType,
4728
+ BaseInteractionContext,
3772
4729
  BaseManager,
4730
+ BitField,
3773
4731
  ButtonBuilder,
3774
4732
  ButtonStyle,
3775
4733
  CHAMELEON_SELF_MAP,
4734
+ CShard,
3776
4735
  Chameleon,
3777
4736
  ChameleonGateway,
3778
4737
  ChameleonREST,
@@ -3780,11 +4739,12 @@ export {
3780
4739
  ChannelManager,
3781
4740
  ChannelType,
3782
4741
  Client,
4742
+ Collection,
3783
4743
  CollectorManager,
3784
4744
  Colors,
3785
4745
  CommandContext,
3786
4746
  CommandManager,
3787
- ComponentContext2 as ComponentContext,
4747
+ ComponentContext,
3788
4748
  ComponentManager,
3789
4749
  ComponentType,
3790
4750
  DISCORD_GATEWAY_OPCODES,
@@ -3792,6 +4752,7 @@ export {
3792
4752
  DefaultMessageNotificationLevel,
3793
4753
  EmbedBuilder,
3794
4754
  EmbedType,
4755
+ EntitlementManager,
3795
4756
  EntitlementType,
3796
4757
  ExplicitContentFilterLevel,
3797
4758
  ForumLayoutType,
@@ -3805,6 +4766,8 @@ export {
3805
4766
  IntegrationExpireBehavior,
3806
4767
  IntentBits,
3807
4768
  Intents,
4769
+ IntentsBitField,
4770
+ InviteManager,
3808
4771
  InviteTargetType,
3809
4772
  InviteType,
3810
4773
  LobbyMemberFlag,
@@ -3816,34 +4779,56 @@ export {
3816
4779
  MessageReferenceType,
3817
4780
  MessageType,
3818
4781
  ModalBuilder,
4782
+ PermissionsBitField,
3819
4783
  PremiumTier,
3820
4784
  PremiumType,
4785
+ RoleManager,
4786
+ ScheduledEventManager,
3821
4787
  SelectMenuBuilder,
4788
+ Shard,
3822
4789
  SkuFlag,
3823
4790
  SkuType,
3824
4791
  SortOrderType,
4792
+ SoundboardManager,
4793
+ StageInstanceManager,
3825
4794
  StagePrivacyLevel,
3826
4795
  StickerFormatType,
3827
4796
  StickerType,
3828
4797
  SubscriptionStatus,
3829
4798
  SystemChannelFlag,
4799
+ TemplateManager,
3830
4800
  TextInputBuilder,
3831
4801
  Tongue,
3832
4802
  TongueStore,
3833
4803
  UserFlag,
4804
+ UserFlagsBitField,
3834
4805
  UserManager,
3835
4806
  VerificationLevel,
3836
4807
  VideoQualityMode,
3837
4808
  VisibilityType,
4809
+ WebhookManager,
3838
4810
  WebhookType,
4811
+ buildAutoModRule,
3839
4812
  buildChannel,
4813
+ buildEmoji,
4814
+ buildEntitlement,
3840
4815
  buildGuild,
4816
+ buildIntegration,
4817
+ buildInteraction,
4818
+ buildInvite,
3841
4819
  buildMember,
3842
4820
  buildMessage,
3843
- buildModalPayload,
3844
4821
  buildRole,
4822
+ buildScheduledEvent,
4823
+ buildStageInstance,
4824
+ buildSticker,
4825
+ buildStickerItem,
3845
4826
  buildUser,
4827
+ buildVoiceState,
4828
+ buildWebhook,
3846
4829
  combinePermissions,
4830
+ computeBasePermissions,
4831
+ computeChannelPermissions,
3847
4832
  defineButton,
3848
4833
  defineChannelSelect,
3849
4834
  defineCommand,
@@ -3863,5 +4848,6 @@ export {
3863
4848
  resolveChannel,
3864
4849
  resolveGuild,
3865
4850
  resolveRole,
3866
- resolveUser
4851
+ resolveUser,
4852
+ serializeComponent
3867
4853
  };