lunibee 0.1.8 → 0.2.1

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.
Files changed (55) hide show
  1. package/README.md +2 -0
  2. package/dist/builders/components.d.ts +30 -2
  3. package/dist/builders/embed.d.ts +7 -7
  4. package/dist/builders/index.d.ts +1 -1
  5. package/dist/builders/index.js +110 -18
  6. package/dist/builders/index.js.map +6 -6
  7. package/dist/collection/index.d.ts +68 -1
  8. package/dist/collection/index.js +334 -1
  9. package/dist/collection/index.js.map +3 -3
  10. package/dist/core/collector.d.ts +13 -0
  11. package/dist/core/events.d.ts +29 -3
  12. package/dist/core/index.d.ts +25 -9
  13. package/dist/core/index.js +1745 -134
  14. package/dist/core/index.js.map +30 -26
  15. package/dist/core/permissions.d.ts +48 -0
  16. package/dist/index.js +2102 -362
  17. package/dist/index.js.map +36 -34
  18. package/dist/managers/advanced.d.ts +116 -0
  19. package/dist/managers/base.d.ts +13 -2
  20. package/dist/managers/emoji.d.ts +1 -1
  21. package/dist/managers/guild-resources.d.ts +22 -2
  22. package/dist/managers/guild.d.ts +31 -3
  23. package/dist/managers/index.d.ts +38 -6
  24. package/dist/managers/index.js +996 -160
  25. package/dist/managers/index.js.map +20 -18
  26. package/dist/managers/member.d.ts +13 -12
  27. package/dist/managers/message.d.ts +21 -4
  28. package/dist/rest/errors.d.ts +33 -0
  29. package/dist/rest/index.d.ts +1 -1
  30. package/dist/rest/index.js +52 -6
  31. package/dist/rest/index.js.map +5 -5
  32. package/dist/rest/routes.d.ts +20 -0
  33. package/dist/sharding/index.d.ts +29 -0
  34. package/dist/sharding/index.js +99 -15
  35. package/dist/sharding/index.js.map +8 -8
  36. package/dist/structures/base.d.ts +38 -0
  37. package/dist/structures/index.d.ts +29 -0
  38. package/dist/structures/index.js +208 -46
  39. package/dist/structures/index.js.map +13 -12
  40. package/dist/structures/interactions.d.ts +51 -1
  41. package/dist/structures/options.d.ts +2 -0
  42. package/dist/structures/resources.d.ts +29 -3
  43. package/dist/types/gateway.d.ts +16 -0
  44. package/dist/types/index.d.ts +67 -1
  45. package/dist/types/index.js.map +3 -3
  46. package/dist/utils/args.d.ts +79 -0
  47. package/dist/utils/index.d.ts +1 -0
  48. package/dist/utils/index.js +190 -2
  49. package/dist/utils/index.js.map +5 -4
  50. package/dist/voice/index.d.ts +3 -0
  51. package/dist/voice/index.js +15 -1
  52. package/dist/voice/index.js.map +3 -3
  53. package/dist/ws/index.js +13 -5
  54. package/dist/ws/index.js.map +6 -6
  55. package/package.json +14 -14
@@ -53,8 +53,11 @@ var Permission = {
53
53
  createEvents: 1n << 44n,
54
54
  useExternalSounds: 1n << 45n,
55
55
  sendVoiceMessages: 1n << 46n,
56
+ setVoiceChannelStatus: 1n << 48n,
56
57
  sendPolls: 1n << 49n,
57
- useExternalApps: 1n << 50n
58
+ useExternalApps: 1n << 50n,
59
+ pinMessages: 1n << 51n,
60
+ bypassSlowmode: 1n << 52n
58
61
  };
59
62
  var Permissions = {
60
63
  CreateInstantInvite: 1n << 0n,
@@ -104,8 +107,11 @@ var Permissions = {
104
107
  CreateEvents: 1n << 44n,
105
108
  UseExternalSounds: 1n << 45n,
106
109
  SendVoiceMessages: 1n << 46n,
110
+ SetVoiceChannelStatus: 1n << 48n,
107
111
  SendPolls: 1n << 49n,
108
- UseExternalApps: 1n << 50n
112
+ UseExternalApps: 1n << 50n,
113
+ PinMessages: 1n << 51n,
114
+ BypassSlowmode: 1n << 52n
109
115
  };
110
116
  var PermissionFlagsBits = {
111
117
  CreateInstantInvite: 1n << 0n,
@@ -155,8 +161,11 @@ var PermissionFlagsBits = {
155
161
  CreateEvents: 1n << 44n,
156
162
  UseExternalSounds: 1n << 45n,
157
163
  SendVoiceMessages: 1n << 46n,
164
+ SetVoiceChannelStatus: 1n << 48n,
158
165
  SendPolls: 1n << 49n,
159
- UseExternalApps: 1n << 50n
166
+ UseExternalApps: 1n << 50n,
167
+ PinMessages: 1n << 51n,
168
+ BypassSlowmode: 1n << 52n
160
169
  };
161
170
 
162
171
  class PermissionSet {
@@ -358,6 +367,10 @@ class PermissionSet {
358
367
  }
359
368
  return false;
360
369
  }
370
+ missing(...permissions) {
371
+ const wanted = new PermissionSet(permissions);
372
+ return wanted.toArray().filter((name) => !this.has(name));
373
+ }
361
374
  add(...permissions) {
362
375
  let bitfield = this.bitfield;
363
376
  for (let i = 0;i < permissions.length; i++) {
@@ -383,6 +396,11 @@ class PermissionSet {
383
396
  toArray() {
384
397
  return Object.keys(Permission).filter((permission) => this.has(permission));
385
398
  }
399
+ static #renamed = {
400
+ ManageEmojisAndStickers: "ManageGuildExpressions",
401
+ ManageEmojis: "ManageGuildExpressions",
402
+ UseSlashCommands: "UseApplicationCommands"
403
+ };
386
404
  #resolve(permission) {
387
405
  if (typeof permission === "bigint")
388
406
  return permission;
@@ -397,6 +415,9 @@ class PermissionSet {
397
415
  return bit;
398
416
  }
399
417
  if (typeof permission === "string") {
418
+ const renamed = PermissionSet.#renamed[permission];
419
+ if (renamed)
420
+ return this.#resolve(renamed);
400
421
  if (permission in Permission)
401
422
  return Permission[permission];
402
423
  if (permission in Permissions)
@@ -419,6 +440,35 @@ class PermissionsBitField extends PermissionSet {
419
440
  super(value);
420
441
  }
421
442
  }
443
+ var ALL_PERMISSIONS = Object.values(Permission).reduce((bits, bit) => bits | bit, 0n);
444
+ var bits = (value) => new PermissionSet(value).bitfield;
445
+ function computePermissions(context) {
446
+ if (context.ownerId !== undefined && context.ownerId === context.memberId)
447
+ return new PermissionSet(ALL_PERMISSIONS);
448
+ const roles = new Map(context.roles.map((role) => [role.id, role]));
449
+ let base = bits(roles.get(context.guildId)?.permissions ?? 0n);
450
+ for (const id of context.memberRoleIds)
451
+ base |= bits(roles.get(id)?.permissions ?? 0n);
452
+ if (base & Permission.administrator)
453
+ return new PermissionSet(ALL_PERMISSIONS);
454
+ const overwrites = context.overwrites ?? [];
455
+ const everyone = overwrites.find((o) => o.id === context.guildId);
456
+ if (everyone)
457
+ base = base & ~bits(everyone.deny) | bits(everyone.allow);
458
+ const memberRoles = new Set(context.memberRoleIds);
459
+ let allow = 0n;
460
+ let deny = 0n;
461
+ for (const overwrite of overwrites)
462
+ if (overwrite.type === 0 /* Role */ && overwrite.id !== context.guildId && memberRoles.has(overwrite.id)) {
463
+ allow |= bits(overwrite.allow);
464
+ deny |= bits(overwrite.deny);
465
+ }
466
+ base = base & ~deny | allow;
467
+ const member = overwrites.find((o) => o.type === 1 /* Member */ && o.id === context.memberId);
468
+ if (member)
469
+ base = base & ~bits(member.deny) | bits(member.allow);
470
+ return new PermissionSet(base);
471
+ }
422
472
  // packages/core/src/events.ts
423
473
  var ClientEvent;
424
474
  ((ClientEvent) => {
@@ -455,6 +505,13 @@ var ClientEvent;
455
505
  ClientEvent["GuildRoleDelete"] = "guildRoleDelete";
456
506
  ClientEvent["GuildEmojisUpdate"] = "guildEmojisUpdate";
457
507
  ClientEvent["GuildStickersUpdate"] = "guildStickersUpdate";
508
+ ClientEvent["EntitlementCreate"] = "entitlementCreate";
509
+ ClientEvent["EntitlementUpdate"] = "entitlementUpdate";
510
+ ClientEvent["EntitlementDelete"] = "entitlementDelete";
511
+ ClientEvent["SoundboardSoundCreate"] = "soundboardSoundCreate";
512
+ ClientEvent["SoundboardSoundUpdate"] = "soundboardSoundUpdate";
513
+ ClientEvent["SoundboardSoundDelete"] = "soundboardSoundDelete";
514
+ ClientEvent["SoundboardSoundsUpdate"] = "soundboardSoundsUpdate";
458
515
  ClientEvent["GuildIntegrationsUpdate"] = "guildIntegrationsUpdate";
459
516
  ClientEvent["GuildScheduledEventCreate"] = "guildScheduledEventCreate";
460
517
  ClientEvent["GuildScheduledEventUpdate"] = "guildScheduledEventUpdate";
@@ -497,6 +554,9 @@ class Collector extends EventEmitter {
497
554
  endReason;
498
555
  totalProcessed = 0;
499
556
  #timeoutTimer;
557
+ #idleTimer;
558
+ #onAbort = () => this.stop("abort");
559
+ #cleanup = [];
500
560
  constructor(options = {}) {
501
561
  super();
502
562
  this.options = options;
@@ -505,6 +565,27 @@ class Collector extends EventEmitter {
505
565
  this.stop("time");
506
566
  }, options.time);
507
567
  }
568
+ this.#resetIdle();
569
+ if (options.signal?.aborted)
570
+ this.stop("abort");
571
+ else
572
+ options.signal?.addEventListener("abort", this.#onAbort, {
573
+ once: true
574
+ });
575
+ }
576
+ onDispose(cleanup) {
577
+ if (this.ended)
578
+ cleanup();
579
+ else
580
+ this.#cleanup.push(cleanup);
581
+ return this;
582
+ }
583
+ #resetIdle() {
584
+ if (!this.options.idle || this.options.idle <= 0)
585
+ return;
586
+ if (this.#idleTimer)
587
+ clearTimeout(this.#idleTimer);
588
+ this.#idleTimer = setTimeout(() => this.stop("idle"), this.options.idle);
508
589
  }
509
590
  async handle(key, item) {
510
591
  if (this.ended)
@@ -522,6 +603,7 @@ class Collector extends EventEmitter {
522
603
  return false;
523
604
  }
524
605
  this.collected.set(key, item);
606
+ this.#resetIdle();
525
607
  this.emit("collect", item);
526
608
  if (this.options.max && this.collected.size >= this.options.max) {
527
609
  this.stop("limit");
@@ -540,9 +622,53 @@ class Collector extends EventEmitter {
540
622
  this.endReason = reason;
541
623
  if (this.#timeoutTimer)
542
624
  clearTimeout(this.#timeoutTimer);
625
+ if (this.#idleTimer)
626
+ clearTimeout(this.#idleTimer);
627
+ this.options.signal?.removeEventListener("abort", this.#onAbort);
628
+ for (const cleanup of this.#cleanup.splice(0)) {
629
+ try {
630
+ cleanup();
631
+ } catch {}
632
+ }
543
633
  this.emit("end", this.collected, reason);
544
634
  this.removeAllListeners();
545
635
  }
636
+ wait() {
637
+ if (this.ended)
638
+ return Promise.resolve(this.collected);
639
+ return new Promise((resolve) => this.once("end", (collected) => resolve(collected)));
640
+ }
641
+ async* [Symbol.asyncIterator]() {
642
+ const queue = [];
643
+ let wake;
644
+ const onCollect = (item) => {
645
+ queue.push(item);
646
+ wake?.();
647
+ };
648
+ const onEnd = () => wake?.();
649
+ if (!this.ended) {
650
+ this.on("collect", onCollect);
651
+ this.on("end", onEnd);
652
+ }
653
+ try {
654
+ for (;; ) {
655
+ if (queue.length > 0) {
656
+ yield queue.shift();
657
+ continue;
658
+ }
659
+ if (this.ended)
660
+ return;
661
+ await new Promise((resolve) => wake = resolve);
662
+ wake = undefined;
663
+ }
664
+ } finally {
665
+ this.off("collect", onCollect);
666
+ this.off("end", onEnd);
667
+ }
668
+ }
669
+ [Symbol.dispose]() {
670
+ this.stop("disposed");
671
+ }
546
672
  next() {
547
673
  return new Promise((resolve, reject) => {
548
674
  if (this.ended) {
@@ -686,7 +812,340 @@ var InteractionResponseType = {
686
812
  Modal: 9
687
813
  };
688
814
  // packages/collection/src/index.ts
815
+ class RecencyList {
816
+ #nodes = new Map;
817
+ #oldest;
818
+ #newest;
819
+ get size() {
820
+ return this.#nodes.size;
821
+ }
822
+ oldest() {
823
+ return this.#oldest?.key;
824
+ }
825
+ touch(key) {
826
+ const node = this.#nodes.get(key);
827
+ if (node)
828
+ return this.#moveNewest(node);
829
+ const created = { key, older: this.#newest };
830
+ if (this.#newest)
831
+ this.#newest.newer = created;
832
+ else
833
+ this.#oldest = created;
834
+ this.#newest = created;
835
+ this.#nodes.set(key, created);
836
+ }
837
+ promote(key) {
838
+ const node = this.#nodes.get(key);
839
+ if (node)
840
+ this.#moveNewest(node);
841
+ }
842
+ delete(key) {
843
+ const node = this.#nodes.get(key);
844
+ if (!node)
845
+ return false;
846
+ this.#unlink(node);
847
+ this.#nodes.delete(key);
848
+ return true;
849
+ }
850
+ clear() {
851
+ this.#nodes.clear();
852
+ this.#oldest = this.#newest = undefined;
853
+ }
854
+ #unlink(node) {
855
+ if (node.older)
856
+ node.older.newer = node.newer;
857
+ else
858
+ this.#oldest = node.newer;
859
+ if (node.newer)
860
+ node.newer.older = node.older;
861
+ else
862
+ this.#newest = node.older;
863
+ node.older = node.newer = undefined;
864
+ }
865
+ #moveNewest(node) {
866
+ if (node === this.#newest)
867
+ return;
868
+ this.#unlink(node);
869
+ node.older = this.#newest;
870
+ if (this.#newest)
871
+ this.#newest.newer = node;
872
+ else
873
+ this.#oldest = node;
874
+ this.#newest = node;
875
+ }
876
+ }
877
+ function assertTTL(ttl) {
878
+ if (ttl !== undefined && (!Number.isFinite(ttl) || ttl <= 0))
879
+ throw new RangeError("TTL must be a positive number, or omitted.");
880
+ }
881
+
689
882
  class Collection extends Map {
883
+ #ttl;
884
+ #maxSize;
885
+ #onEvict;
886
+ #expiry = new Map;
887
+ #lru = new RecencyList;
888
+ #stats = {
889
+ hits: 0,
890
+ misses: 0,
891
+ expired: 0,
892
+ evicted: 0
893
+ };
894
+ #heap = [];
895
+ #timer;
896
+ #armedFor = Infinity;
897
+ constructor(entries, options = {}) {
898
+ super();
899
+ assertTTL(options.ttl);
900
+ if (options.maxSize !== undefined && (!Number.isInteger(options.maxSize) || options.maxSize <= 0))
901
+ throw new RangeError("maxSize must be a positive integer.");
902
+ this.#ttl = options.ttl;
903
+ this.#maxSize = options.maxSize;
904
+ this.#onEvict = options.onEvict;
905
+ if (entries)
906
+ for (const [key, value] of entries)
907
+ this.set(key, value);
908
+ }
909
+ set(key, value, ttl) {
910
+ assertTTL(ttl);
911
+ const window = ttl ?? this.#ttl;
912
+ if (this.#maxSize !== undefined) {
913
+ this.#lru.touch(key);
914
+ }
915
+ super.set(key, value);
916
+ if (window !== undefined)
917
+ this.#schedule(key, window);
918
+ else if (this.#expiry.size > 0)
919
+ this.#expiry.delete(key);
920
+ this.#enforceCap();
921
+ return this;
922
+ }
923
+ setWithoutTTL(key, value) {
924
+ if (this.#expiry.size > 0)
925
+ this.#expiry.delete(key);
926
+ if (this.#lru.size > 0)
927
+ this.#lru.delete(key);
928
+ super.set(key, value);
929
+ return this;
930
+ }
931
+ get(key) {
932
+ if (this.#expireIfDue(key)) {
933
+ this.#stats.misses++;
934
+ return;
935
+ }
936
+ const value = super.get(key);
937
+ if (value === undefined && !super.has(key)) {
938
+ this.#stats.misses++;
939
+ return;
940
+ }
941
+ this.#stats.hits++;
942
+ const expiry = this.#expiry.get(key);
943
+ if (expiry)
944
+ expiry.deadline = Date.now() + expiry.window;
945
+ this.#lru.promote(key);
946
+ return value;
947
+ }
948
+ peek(key) {
949
+ if (!this.#expireIfDue(key) && super.has(key)) {
950
+ this.#stats.hits++;
951
+ return super.get(key);
952
+ }
953
+ this.#stats.misses++;
954
+ return;
955
+ }
956
+ get stats() {
957
+ return { ...this.#stats };
958
+ }
959
+ has(key) {
960
+ return !this.#expireIfDue(key) && super.has(key);
961
+ }
962
+ delete(key) {
963
+ if (this.#expireIfDue(key))
964
+ return false;
965
+ this.#expiry.delete(key);
966
+ this.#lru.delete(key);
967
+ return super.delete(key);
968
+ }
969
+ clear() {
970
+ super.clear();
971
+ this.#expiry.clear();
972
+ this.#lru.clear();
973
+ this.#heap.length = 0;
974
+ if (this.#timer)
975
+ clearTimeout(this.#timer);
976
+ this.#timer = undefined;
977
+ this.#armedFor = Infinity;
978
+ }
979
+ get size() {
980
+ this.purge();
981
+ return super.size;
982
+ }
983
+ entries() {
984
+ this.purge();
985
+ return super.entries();
986
+ }
987
+ keys() {
988
+ this.purge();
989
+ return super.keys();
990
+ }
991
+ values() {
992
+ this.purge();
993
+ return super.values();
994
+ }
995
+ [Symbol.iterator]() {
996
+ return this.entries();
997
+ }
998
+ forEach(callback, thisArg) {
999
+ this.purge();
1000
+ super.forEach(callback, thisArg);
1001
+ }
1002
+ ttlRemaining(key) {
1003
+ if (this.#expireIfDue(key))
1004
+ return;
1005
+ const expiry = this.#expiry.get(key);
1006
+ return expiry && Math.max(0, expiry.deadline - Date.now());
1007
+ }
1008
+ purge() {
1009
+ if (this.#expiry.size === 0)
1010
+ return 0;
1011
+ const now = Date.now();
1012
+ let removed = 0;
1013
+ const dropped = [];
1014
+ while (this.#nextDeadline() <= now) {
1015
+ const due = this.#heapPop();
1016
+ dropped.push([due.key, super.get(due.key)]);
1017
+ this.#remove(due.key);
1018
+ removed++;
1019
+ }
1020
+ this.#stats.expired += removed;
1021
+ this.#rearm();
1022
+ for (const [key, value] of dropped)
1023
+ this.#notify(key, value, "expired");
1024
+ return removed;
1025
+ }
1026
+ #expireIfDue(key) {
1027
+ const expiry = this.#expiry.get(key);
1028
+ if (!expiry || expiry.deadline > Date.now())
1029
+ return false;
1030
+ const value = super.get(key);
1031
+ this.#remove(key);
1032
+ this.#stats.expired++;
1033
+ this.#notify(key, value, "expired");
1034
+ return true;
1035
+ }
1036
+ #remove(key) {
1037
+ this.#expiry.delete(key);
1038
+ this.#lru.delete(key);
1039
+ super.delete(key);
1040
+ }
1041
+ #notify(key, value, reason) {
1042
+ if (!this.#onEvict)
1043
+ return;
1044
+ try {
1045
+ this.#onEvict(key, value, reason);
1046
+ } catch {}
1047
+ }
1048
+ #enforceCap() {
1049
+ if (this.#maxSize === undefined)
1050
+ return;
1051
+ while (this.#lru.size > this.#maxSize) {
1052
+ const oldest = this.#lru.oldest();
1053
+ const value = super.get(oldest);
1054
+ this.#remove(oldest);
1055
+ this.#stats.evicted++;
1056
+ this.#notify(oldest, value, "evicted");
1057
+ }
1058
+ }
1059
+ #schedule(key, window) {
1060
+ const deadline = Date.now() + window;
1061
+ const expiry = this.#expiry.get(key);
1062
+ if (expiry) {
1063
+ expiry.deadline = deadline;
1064
+ expiry.window = window;
1065
+ if (deadline >= expiry.filed)
1066
+ return;
1067
+ expiry.filed = deadline;
1068
+ } else
1069
+ this.#expiry.set(key, { deadline, window, filed: deadline });
1070
+ this.#heapPush({ key, deadline });
1071
+ if (this.#heap.length > 2 * this.#expiry.size + 8)
1072
+ this.#compact();
1073
+ this.#rearm();
1074
+ }
1075
+ #nextDeadline() {
1076
+ for (;; ) {
1077
+ const top = this.#heap[0];
1078
+ if (top === undefined)
1079
+ return Infinity;
1080
+ const expiry = this.#expiry.get(top.key);
1081
+ if (!expiry || expiry.filed !== top.deadline) {
1082
+ this.#heapPop();
1083
+ continue;
1084
+ }
1085
+ if (expiry.deadline === top.deadline)
1086
+ return top.deadline;
1087
+ this.#heapPop();
1088
+ expiry.filed = expiry.deadline;
1089
+ this.#heapPush({ key: top.key, deadline: expiry.deadline });
1090
+ }
1091
+ }
1092
+ #compact() {
1093
+ const live = this.#heap.filter((record) => this.#expiry.get(record.key)?.filed === record.deadline);
1094
+ this.#heap.length = 0;
1095
+ for (const record of live)
1096
+ this.#heapPush(record);
1097
+ }
1098
+ #rearm() {
1099
+ const deadline = this.#nextDeadline();
1100
+ if (this.#timer !== undefined && deadline >= this.#armedFor)
1101
+ return;
1102
+ if (this.#timer)
1103
+ clearTimeout(this.#timer);
1104
+ this.#timer = undefined;
1105
+ this.#armedFor = deadline;
1106
+ if (deadline === Infinity)
1107
+ return;
1108
+ this.#timer = setTimeout(() => {
1109
+ this.#timer = undefined;
1110
+ this.#armedFor = Infinity;
1111
+ this.purge();
1112
+ }, Math.max(0, deadline - Date.now()));
1113
+ this.#timer.unref?.();
1114
+ }
1115
+ #heapPush(record) {
1116
+ const heap = this.#heap;
1117
+ heap.push(record);
1118
+ let i = heap.length - 1;
1119
+ while (i > 0) {
1120
+ const parent = i - 1 >> 1;
1121
+ if (heap[parent].deadline <= heap[i].deadline)
1122
+ break;
1123
+ [heap[parent], heap[i]] = [heap[i], heap[parent]];
1124
+ i = parent;
1125
+ }
1126
+ }
1127
+ #heapPop() {
1128
+ const heap = this.#heap;
1129
+ const top = heap[0];
1130
+ const last = heap.pop();
1131
+ if (top === undefined || heap.length === 0)
1132
+ return top;
1133
+ heap[0] = last;
1134
+ for (let i = 0;; ) {
1135
+ const left = 2 * i + 1;
1136
+ const right = left + 1;
1137
+ let smallest = i;
1138
+ if (left < heap.length && heap[left].deadline < heap[smallest].deadline)
1139
+ smallest = left;
1140
+ if (right < heap.length && heap[right].deadline < heap[smallest].deadline)
1141
+ smallest = right;
1142
+ if (smallest === i)
1143
+ break;
1144
+ [heap[smallest], heap[i]] = [heap[i], heap[smallest]];
1145
+ i = smallest;
1146
+ }
1147
+ return top;
1148
+ }
690
1149
  first() {
691
1150
  for (const value of this.values())
692
1151
  return value;
@@ -911,11 +1370,40 @@ class Manager {
911
1370
  has(id) {
912
1371
  return this.cache.has(id);
913
1372
  }
1373
+ #inflight = new Map;
1374
+ fetchOnce(id, load, store = (value) => {
1375
+ this.set(id, value);
1376
+ return value;
1377
+ }) {
1378
+ const pending = this.#inflight.get(id);
1379
+ if (pending)
1380
+ return pending.promise;
1381
+ const entry = {
1382
+ promise: new Promise((resolve) => resolve(load())),
1383
+ dirty: false
1384
+ };
1385
+ this.#inflight.set(id, entry);
1386
+ entry.promise = entry.promise.then((value) => {
1387
+ this.#inflight.delete(id);
1388
+ return entry.dirty ? this.get(id) ?? value : store(value);
1389
+ }, (error) => {
1390
+ this.#inflight.delete(id);
1391
+ throw error;
1392
+ });
1393
+ return entry.promise;
1394
+ }
1395
+ #markDirty(id) {
1396
+ const pending = this.#inflight.get(id);
1397
+ if (pending)
1398
+ pending.dirty = true;
1399
+ }
914
1400
  set(id, value) {
915
- this.cache.set(id, value);
1401
+ this.#markDirty(id);
1402
+ this.cache.setWithoutTTL(id, value);
916
1403
  return this;
917
1404
  }
918
1405
  delete(id) {
1406
+ this.#markDirty(id);
919
1407
  return this.cache.delete(id);
920
1408
  }
921
1409
  clear() {
@@ -951,16 +1439,20 @@ class ResourceManager extends Manager {
951
1439
  async resolve(id) {
952
1440
  return this.get(id) ?? this.fetch(id);
953
1441
  }
954
- async fetch(id) {
955
- const resource = await this.#fetcher(id);
956
- this.set(id, resource);
957
- return resource;
1442
+ fetch(id) {
1443
+ return this.fetchOnce(id, () => this.#fetcher(id));
958
1444
  }
959
1445
  async fetchMany(ids) {
960
1446
  return Promise.all([...ids].map((id) => this.resolve(id)));
961
1447
  }
962
1448
  upsert(resource) {
963
1449
  const key = this.#key(resource);
1450
+ const existing = this.get(key);
1451
+ if (existing !== undefined && existing !== resource && typeof existing === "object" && existing !== null) {
1452
+ Object.assign(existing, resource);
1453
+ this.set(key, existing);
1454
+ return existing;
1455
+ }
964
1456
  this.set(key, resource);
965
1457
  return resource;
966
1458
  }
@@ -971,7 +1463,7 @@ class ResourceManager extends Manager {
971
1463
  // packages/rest/package.json
972
1464
  var package_default = {
973
1465
  name: "@lunibee/rest",
974
- version: "0.1.8",
1466
+ version: "0.2.1",
975
1467
  type: "module",
976
1468
  module: "./src/index.ts",
977
1469
  types: "./src/index.ts",
@@ -1031,7 +1523,29 @@ class MemoryRateLimitStore {
1031
1523
  }
1032
1524
 
1033
1525
  // packages/rest/src/errors.ts
1526
+ function kindFromStatus(status) {
1527
+ if (status === 429)
1528
+ return "rateLimited";
1529
+ if (status === 401)
1530
+ return "authentication";
1531
+ if (status === 403)
1532
+ return "permission";
1533
+ if (status === 404)
1534
+ return "notFound";
1535
+ if (status === 400 || status === 422)
1536
+ return "validation";
1537
+ if (status >= 500)
1538
+ return "server";
1539
+ if (status === 0)
1540
+ return "network";
1541
+ return "client";
1542
+ }
1543
+ function redactPath(path) {
1544
+ return path.replace(/^(\/webhooks\/[^/?]+\/)[^/?]+/, "$1:token").replace(/^(\/interactions\/[^/?]+\/)[^/?]+/, "$1:token");
1545
+ }
1546
+
1034
1547
  class RESTError extends Error {
1548
+ kind;
1035
1549
  status;
1036
1550
  code;
1037
1551
  errors;
@@ -1041,14 +1555,18 @@ class RESTError extends Error {
1041
1555
  super(message, options.cause === undefined ? undefined : { cause: options.cause });
1042
1556
  this.name = "RESTError";
1043
1557
  this.status = status;
1558
+ this.kind = options.kind ?? kindFromStatus(status);
1044
1559
  this.code = code;
1045
1560
  this.errors = errors;
1046
1561
  this.method = options.method;
1047
- this.path = options.path;
1562
+ this.path = options.path === undefined ? undefined : redactPath(options.path);
1563
+ }
1564
+ get retryable() {
1565
+ return this.kind === "rateLimited" || this.kind === "server" || this.kind === "network" || this.kind === "timeout";
1048
1566
  }
1049
1567
  }
1050
1568
  function abortError(path, reason) {
1051
- return new RESTError(reason instanceof Error ? reason.message : "Discord REST request was aborted", 0, undefined, undefined, { path, cause: reason });
1569
+ return new RESTError(reason instanceof Error ? reason.message : "Discord REST request was aborted", 0, undefined, undefined, { path, cause: reason, kind: "aborted" });
1052
1570
  }
1053
1571
  async function sleep(delay, signal, path) {
1054
1572
  if (delay <= 0)
@@ -1383,8 +1901,23 @@ var Routes = {
1383
1901
  invite: (code) => `/invites/${encodeURIComponent(code)}`,
1384
1902
  guildVanity: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/vanity-url`,
1385
1903
  guildEmoji: (guildId, emojiId) => emojiId ? `/guilds/${snowflake(guildId, "Guild ID")}/emojis/${snowflake(emojiId, "Emoji ID")}` : `/guilds/${snowflake(guildId, "Guild ID")}/emojis`,
1386
- applicationEmoji: (applicationId, emojiId) => emojiId ? `/applications/${snowflake(applicationId, "Application ID")}/emojis/${snowflake(emojiId, "Emoji ID")}` : `/applications/${snowflake(applicationId, "Application ID")}/emojis`
1904
+ applicationEmoji: (applicationId, emojiId) => emojiId ? `/applications/${snowflake(applicationId, "Application ID")}/emojis/${snowflake(emojiId, "Emoji ID")}` : `/applications/${snowflake(applicationId, "Application ID")}/emojis`,
1905
+ pollExpire: (channelId, messageId) => `/channels/${snowflake(channelId, "Channel ID")}/polls/${snowflake(messageId, "Message ID")}/expire`,
1906
+ pollAnswerVoters: (channelId, messageId, answerId) => `/channels/${snowflake(channelId, "Channel ID")}/polls/${snowflake(messageId, "Message ID")}/answers/${integer(answerId, "Answer ID")}`,
1907
+ guildSticker: (guildId, stickerId) => stickerId ? `/guilds/${snowflake(guildId, "Guild ID")}/stickers/${snowflake(stickerId, "Sticker ID")}` : `/guilds/${snowflake(guildId, "Guild ID")}/stickers`,
1908
+ sendSoundboardSound: (channelId) => `/channels/${snowflake(channelId, "Channel ID")}/send-soundboard-sound`,
1909
+ soundboardDefaultSounds: () => "/soundboard-default-sounds",
1910
+ guildSoundboardSound: (guildId, soundId) => soundId ? `/guilds/${snowflake(guildId, "Guild ID")}/soundboard-sounds/${snowflake(soundId, "Sound ID")}` : `/guilds/${snowflake(guildId, "Guild ID")}/soundboard-sounds`,
1911
+ applicationSkus: (applicationId) => `/applications/${snowflake(applicationId, "Application ID")}/skus`,
1912
+ applicationEntitlement: (applicationId, entitlementId) => entitlementId ? `/applications/${snowflake(applicationId, "Application ID")}/entitlements/${snowflake(entitlementId, "Entitlement ID")}` : `/applications/${snowflake(applicationId, "Application ID")}/entitlements`,
1913
+ consumeEntitlement: (applicationId, entitlementId) => `/applications/${snowflake(applicationId, "Application ID")}/entitlements/${snowflake(entitlementId, "Entitlement ID")}/consume`,
1914
+ skuSubscription: (skuId, subscriptionId) => subscriptionId ? `/skus/${snowflake(skuId, "SKU ID")}/subscriptions/${snowflake(subscriptionId, "Subscription ID")}` : `/skus/${snowflake(skuId, "SKU ID")}/subscriptions`
1387
1915
  };
1916
+ function integer(value, field) {
1917
+ if (!Number.isInteger(value) || value < 0)
1918
+ throw new TypeError(`${field} must be a non-negative integer.`);
1919
+ return String(value);
1920
+ }
1388
1921
  function snowflake(value, field) {
1389
1922
  if (!/^\d{1,20}$/.test(value))
1390
1923
  throw new TypeError(`${field} must be a valid Discord snowflake.`);
@@ -1521,7 +2054,8 @@ class REST {
1521
2054
  throw new RESTError(failure.message, 0, undefined, undefined, {
1522
2055
  method,
1523
2056
  path,
1524
- cause: failure.cause ?? failure
2057
+ cause: failure.cause ?? failure,
2058
+ kind: failure.timedOut ? "timeout" : "network"
1525
2059
  });
1526
2060
  }
1527
2061
  this.#emit(this.#hooks.onResponse, {
@@ -1620,6 +2154,9 @@ class REST {
1620
2154
  #emit(hook, ctx) {
1621
2155
  if (!hook)
1622
2156
  return;
2157
+ const withPath = ctx;
2158
+ if (typeof withPath.path === "string")
2159
+ ctx = { ...ctx, path: redactPath(withPath.path) };
1623
2160
  Promise.resolve().then(() => hook(ctx)).catch(() => {});
1624
2161
  }
1625
2162
  }
@@ -1696,6 +2233,7 @@ class Channel extends BaseStructure {
1696
2233
  nsfw;
1697
2234
  rateLimitPerUser;
1698
2235
  position;
2236
+ permissionOverwrites;
1699
2237
  #context;
1700
2238
  constructor(data, context) {
1701
2239
  super(data.id);
@@ -1709,6 +2247,7 @@ class Channel extends BaseStructure {
1709
2247
  this.nsfw = data.nsfw;
1710
2248
  this.rateLimitPerUser = data.rate_limit_per_user;
1711
2249
  this.position = data.position;
2250
+ this.permissionOverwrites = (data.permission_overwrites ?? []).map((overwrite) => ({ ...overwrite }));
1712
2251
  this.#context = context;
1713
2252
  }
1714
2253
  sendMessage(options) {
@@ -1732,6 +2271,11 @@ class Channel extends BaseStructure {
1732
2271
  editTopic(topic) {
1733
2272
  return this.edit({ topic });
1734
2273
  }
2274
+ editPermissionOverwrite(targetId, changes, options) {
2275
+ if (!this.#context?.editPermissionOverwrite)
2276
+ throw new Error("This channel is not attached to a client.");
2277
+ return this.#context.editPermissionOverwrite(this.id, targetId, changes, options);
2278
+ }
1735
2279
  editParent(parentId) {
1736
2280
  return this.edit({ parent_id: parentId });
1737
2281
  }
@@ -1866,7 +2410,148 @@ class Guild extends BaseStructure {
1866
2410
  return this.name;
1867
2411
  }
1868
2412
  }
2413
+
1869
2414
  // packages/structures/src/resources.ts
2415
+ function toDateOrNull(value) {
2416
+ if (!value)
2417
+ return null;
2418
+ const date = new Date(value);
2419
+ return Number.isNaN(date.getTime()) ? null : date;
2420
+ }
2421
+
2422
+ class GuildMember {
2423
+ user;
2424
+ guildId;
2425
+ nickname;
2426
+ roleIds;
2427
+ pending;
2428
+ joinedAt;
2429
+ avatarHash;
2430
+ premiumSince;
2431
+ timedOutUntil;
2432
+ flags;
2433
+ #suppliedPermissions;
2434
+ #context;
2435
+ constructor(data, context) {
2436
+ this.user = new User(data.user);
2437
+ this.#context = context;
2438
+ if (!/^\d{1,20}$/.test(data.guild_id))
2439
+ throw new TypeError("Member guild_id must be a valid snowflake.");
2440
+ this.guildId = data.guild_id;
2441
+ this.nickname = data.nick ?? null;
2442
+ this.roleIds = [...data.roles ?? []];
2443
+ this.pending = data.pending ?? false;
2444
+ this.joinedAt = data.joined_at ? new Date(data.joined_at) : undefined;
2445
+ if (this.joinedAt?.toString() === "Invalid Date")
2446
+ throw new RangeError("Member joined_at must be a valid date.");
2447
+ if (data.permissions !== undefined)
2448
+ this.#suppliedPermissions = new PermissionsBitField(data.permissions);
2449
+ this.avatarHash = data.avatar ?? null;
2450
+ this.premiumSince = toDateOrNull(data.premium_since);
2451
+ this.timedOutUntil = toDateOrNull(data.communication_disabled_until);
2452
+ this.flags = data.flags ?? 0;
2453
+ }
2454
+ get permissions() {
2455
+ if (this.#suppliedPermissions)
2456
+ return this.#suppliedPermissions;
2457
+ return new PermissionsBitField(this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds) ?? 0n);
2458
+ }
2459
+ permissionsIn(channelId) {
2460
+ const computed = this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds, channelId);
2461
+ return computed ? new PermissionsBitField(computed) : null;
2462
+ }
2463
+ #action(name) {
2464
+ const action = this.#context?.[name];
2465
+ if (!action)
2466
+ throw new Error("This member is not attached to a client.");
2467
+ return action;
2468
+ }
2469
+ kick(reason) {
2470
+ return this.#action("kickMember")(this.guildId, this.user.id, reason);
2471
+ }
2472
+ ban(options = {}) {
2473
+ return this.#action("banMember")(this.guildId, this.user.id, options);
2474
+ }
2475
+ edit(options, reason) {
2476
+ return this.#action("editMember")(this.guildId, this.user.id, options, reason);
2477
+ }
2478
+ timeout(milliseconds, reason) {
2479
+ if (milliseconds !== null && !(milliseconds > 0))
2480
+ throw new RangeError("Timeout length must be a positive number of milliseconds.");
2481
+ return this.edit({
2482
+ communication_disabled_until: milliseconds === null ? null : new Date(Date.now() + milliseconds).toISOString()
2483
+ }, reason);
2484
+ }
2485
+ setNickname(nickname, reason) {
2486
+ return this.edit({ nick: nickname }, reason);
2487
+ }
2488
+ addRole(roleId, reason) {
2489
+ return this.#action("addMemberRole")(this.guildId, this.user.id, roleId, reason);
2490
+ }
2491
+ removeRole(roleId, reason) {
2492
+ return this.#action("removeMemberRole")(this.guildId, this.user.id, roleId, reason);
2493
+ }
2494
+ get displayName() {
2495
+ return this.nickname ?? this.user.displayName;
2496
+ }
2497
+ get isTimedOut() {
2498
+ return this.timedOutUntil !== null && this.timedOutUntil > new Date;
2499
+ }
2500
+ avatarURL(options = {}) {
2501
+ if (this.avatarHash)
2502
+ return cdnURL(`/guilds/${this.guildId}/users/${this.user.id}/avatars`, this.avatarHash, options);
2503
+ return this.user.avatarURL(options);
2504
+ }
2505
+ displayAvatarURL(options = {}) {
2506
+ return this.avatarURL(options) ?? this.user.displayAvatarURL(options);
2507
+ }
2508
+ toString() {
2509
+ return this.user.toString();
2510
+ }
2511
+ }
2512
+
2513
+ class Role extends BaseStructure {
2514
+ name;
2515
+ color;
2516
+ hoist;
2517
+ permissions;
2518
+ managed;
2519
+ mentionable;
2520
+ position;
2521
+ unicodeEmoji;
2522
+ iconHash;
2523
+ tags;
2524
+ constructor(data) {
2525
+ super(data.id);
2526
+ if (!data.name)
2527
+ throw new TypeError("Role name cannot be empty.");
2528
+ this.name = data.name;
2529
+ this.color = data.color ?? 0;
2530
+ this.hoist = data.hoist ?? false;
2531
+ this.permissions = new PermissionsBitField(data.permissions ?? 0n);
2532
+ this.managed = data.managed ?? false;
2533
+ this.mentionable = data.mentionable ?? false;
2534
+ this.position = data.position ?? 0;
2535
+ this.unicodeEmoji = data.unicode_emoji ?? null;
2536
+ this.iconHash = data.icon ?? null;
2537
+ this.tags = data.tags ?? null;
2538
+ }
2539
+ get colorHex() {
2540
+ return `#${this.color.toString(16).padStart(6, "0").toUpperCase()}`;
2541
+ }
2542
+ iconURL(options = {}) {
2543
+ if (!this.iconHash)
2544
+ return null;
2545
+ return cdnURL(`/role-icons/${this.id}`, this.iconHash, options);
2546
+ }
2547
+ isEveryone(guildId) {
2548
+ return this.id === guildId;
2549
+ }
2550
+ toString() {
2551
+ return `<@&${this.id}>`;
2552
+ }
2553
+ }
2554
+
1870
2555
  class TextChannel extends Channel {
1871
2556
  constructor(data, context) {
1872
2557
  super(data, context);
@@ -1875,6 +2560,38 @@ class TextChannel extends Channel {
1875
2560
  return `<#${this.id}>`;
1876
2561
  }
1877
2562
  }
2563
+ class Emoji extends BaseStructure {
2564
+ name;
2565
+ roleIds;
2566
+ user;
2567
+ requireColons;
2568
+ managed;
2569
+ animated;
2570
+ available;
2571
+ constructor(data) {
2572
+ super(data.id ?? "0");
2573
+ if (data.id === null)
2574
+ this.id = "unicode";
2575
+ this.name = data.name;
2576
+ this.roleIds = data.roles ?? [];
2577
+ this.user = data.user ? new User(data.user) : null;
2578
+ this.requireColons = data.require_colons ?? false;
2579
+ this.managed = data.managed ?? false;
2580
+ this.animated = data.animated ?? false;
2581
+ this.available = data.available ?? true;
2582
+ }
2583
+ url(options = {}) {
2584
+ if (!this.id || this.id === "unicode")
2585
+ return null;
2586
+ const ext = options.extension ?? (this.animated ? "gif" : "png");
2587
+ const size = options.size ? `?size=${options.size}` : "";
2588
+ return `${CDN_BASE}/emojis/${this.id}.${ext}${size}`;
2589
+ }
2590
+ toString() {
2591
+ return this.id !== "unicode" ? `<${this.animated ? "a" : ""}:${this.name}:${this.id}>` : this.name ?? "";
2592
+ }
2593
+ }
2594
+
1878
2595
  class AutoModerationRule extends BaseStructure {
1879
2596
  guildId;
1880
2597
  name;
@@ -2167,6 +2884,17 @@ class CommandOptions {
2167
2884
  throw new TypeError(`Resolved mentionable for option "${name}" is missing.`);
2168
2885
  return resolved;
2169
2886
  }
2887
+ getMentionableType(name) {
2888
+ const opt = this.#get(name);
2889
+ if (!opt || opt.type !== OptionType.Mentionable)
2890
+ return null;
2891
+ const id = String(opt.value);
2892
+ if (this.#resolved?.users?.[id])
2893
+ return "user";
2894
+ if (this.#resolved?.roles?.[id])
2895
+ return "role";
2896
+ return null;
2897
+ }
2170
2898
  getAttachment(name, required = false) {
2171
2899
  const opt = this.#get(name);
2172
2900
  if (!opt || opt.type !== OptionType.Attachment) {
@@ -2192,6 +2920,17 @@ var InteractionType = {
2192
2920
  ApplicationCommandAutocomplete: 4,
2193
2921
  ModalSubmit: 5
2194
2922
  };
2923
+ var EPHEMERAL = 64;
2924
+ var TOKEN_LIFETIME_MS = 15 * 60000;
2925
+ var DISCORD_EPOCH = 1420070400000n;
2926
+ function toMessageData(options) {
2927
+ if (typeof options === "string")
2928
+ return { content: options };
2929
+ const { ephemeral, ...data } = options;
2930
+ if (ephemeral)
2931
+ data.flags = (typeof data.flags === "number" ? data.flags : 0) | EPHEMERAL;
2932
+ return data;
2933
+ }
2195
2934
 
2196
2935
  class InteractionResponse {
2197
2936
  type;
@@ -2206,14 +2945,10 @@ class InteractionResponse {
2206
2945
  return this.data === undefined ? { type: this.type } : { type: this.type, data: this.data };
2207
2946
  }
2208
2947
  static message(options) {
2209
- const data = { ...options };
2210
- if (options.ephemeral) {
2211
- data.flags = (typeof options.flags === "number" ? options.flags : 0) | 64;
2212
- }
2213
- return new InteractionResponse(InteractionResponseType.ChannelMessage, data);
2948
+ return new InteractionResponse(InteractionResponseType.ChannelMessage, toMessageData(options));
2214
2949
  }
2215
2950
  static defer(ephemeral = false) {
2216
- return new InteractionResponse(InteractionResponseType.DeferredChannelMessage, ephemeral ? { flags: 64 } : undefined);
2951
+ return new InteractionResponse(InteractionResponseType.DeferredChannelMessage, ephemeral ? { flags: EPHEMERAL } : undefined);
2217
2952
  }
2218
2953
  static pong() {
2219
2954
  return new InteractionResponse(InteractionResponseType.Pong);
@@ -2231,6 +2966,7 @@ class Interaction {
2231
2966
  replied = false;
2232
2967
  deferred = false;
2233
2968
  #client;
2969
+ #acknowledging = false;
2234
2970
  constructor(client, data) {
2235
2971
  if (!data.id || !data.token)
2236
2972
  throw new TypeError("Interaction ID and token are required.");
@@ -2246,6 +2982,20 @@ class Interaction {
2246
2982
  isChatInputCommand() {
2247
2983
  return this.type === InteractionType.ApplicationCommand;
2248
2984
  }
2985
+ awaitModalSubmit(options) {
2986
+ const collect = this.#client.resourceContext?.collectInteractions;
2987
+ if (!collect)
2988
+ return Promise.reject(new Error("This interaction is not attached to a client."));
2989
+ if (!(options.time > 0))
2990
+ return Promise.reject(new RangeError("awaitModalSubmit needs a positive time."));
2991
+ const userId = this.user?.id;
2992
+ const collector = collect({
2993
+ time: options.time,
2994
+ max: 1,
2995
+ filter: async (interaction) => interaction.isModalSubmit() && interaction.user?.id === userId && (options.customId === undefined || interaction.customId === options.customId) && (options.filter ? await options.filter(interaction) : true)
2996
+ });
2997
+ return collector.next();
2998
+ }
2249
2999
  isMessageComponent() {
2250
3000
  return this.type === InteractionType.MessageComponent;
2251
3001
  }
@@ -2280,9 +3030,57 @@ class Interaction {
2280
3030
  return [3, 5, 6, 7, 8].includes(this.#componentType());
2281
3031
  }
2282
3032
  assertUnacknowledged() {
2283
- if (this.replied || this.deferred)
3033
+ if (this.replied || this.deferred || this.#acknowledging)
2284
3034
  throw new Error("Interaction has already been acknowledged.");
2285
3035
  }
3036
+ async acknowledge(response, state) {
3037
+ this.assertUnacknowledged();
3038
+ this.#acknowledging = true;
3039
+ try {
3040
+ const result = await this.postResponse(response);
3041
+ this[state] = true;
3042
+ return result;
3043
+ } finally {
3044
+ this.#acknowledging = false;
3045
+ }
3046
+ }
3047
+ get user() {
3048
+ const raw = this.data.member?.user ?? this.data.user;
3049
+ return raw ? new User(raw) : null;
3050
+ }
3051
+ get member() {
3052
+ const raw = this.data.member;
3053
+ if (!raw || !this.guildId)
3054
+ return null;
3055
+ return new GuildMember({
3056
+ ...raw,
3057
+ guild_id: this.guildId
3058
+ }, this.#client.resourceContext);
3059
+ }
3060
+ get createdTimestamp() {
3061
+ return Number((BigInt(this.id) >> 22n) + DISCORD_EPOCH);
3062
+ }
3063
+ get expiresAt() {
3064
+ return new Date(this.createdTimestamp + TOKEN_LIFETIME_MS);
3065
+ }
3066
+ get isExpired() {
3067
+ return Date.now() >= this.createdTimestamp + TOKEN_LIFETIME_MS;
3068
+ }
3069
+ #webhookMessage(method, messageId, data) {
3070
+ if (!this.#client.interactionWebhookMessage)
3071
+ return Promise.reject(new Error("This interaction client does not support webhook message access."));
3072
+ return this.#client.interactionWebhookMessage(method, this.applicationId, this.token, messageId, data);
3073
+ }
3074
+ fetchReply() {
3075
+ this.assertAcknowledged();
3076
+ return this.#webhookMessage("GET", "@original");
3077
+ }
3078
+ editFollowUp(messageId, options) {
3079
+ return this.#webhookMessage("PATCH", messageId, toMessageData(options));
3080
+ }
3081
+ async deleteFollowUp(messageId) {
3082
+ await this.#webhookMessage("DELETE", messageId);
3083
+ }
2286
3084
  assertAcknowledged() {
2287
3085
  if (!this.replied && !this.deferred)
2288
3086
  throw new Error("Interaction has not been acknowledged.");
@@ -2291,41 +3089,29 @@ class Interaction {
2291
3089
  return this.#client.postInteractionResponse(this.id, this.token, response);
2292
3090
  }
2293
3091
  async reply(options) {
2294
- this.assertUnacknowledged();
2295
- const payload = typeof options === "string" ? { content: options } : options;
2296
- const result = await this.#client.postInteractionResponse(this.id, this.token, InteractionResponse.message(payload));
2297
- this.replied = true;
2298
- return result;
3092
+ return this.acknowledge(InteractionResponse.message(toMessageData(options)), "replied");
2299
3093
  }
2300
- async deferReply(ephemeral = false) {
2301
- this.assertUnacknowledged();
2302
- await this.#client.postInteractionResponse(this.id, this.token, InteractionResponse.defer(ephemeral));
2303
- this.deferred = true;
3094
+ async deferReply(options = false) {
3095
+ const ephemeral = typeof options === "boolean" ? options : options.ephemeral === true;
3096
+ await this.acknowledge(InteractionResponse.defer(ephemeral), "deferred");
2304
3097
  }
2305
3098
  editReply(options) {
2306
3099
  this.assertAcknowledged();
2307
- return this.#client.editInteractionReply(this.token, options);
3100
+ return this.#client.editInteractionReply(this.token, toMessageData(options));
2308
3101
  }
2309
3102
  deleteReply() {
2310
3103
  this.assertAcknowledged();
2311
3104
  return this.#client.deleteInteractionReply(this.token);
2312
3105
  }
2313
3106
  followUp(options) {
2314
- const payload = typeof options === "string" ? { content: options } : options;
2315
- return this.#client.followUpInteraction(this.token, payload);
3107
+ return this.#client.followUpInteraction(this.token, toMessageData(options));
2316
3108
  }
2317
3109
  async update(options) {
2318
- this.assertUnacknowledged();
2319
- const payload = typeof options === "string" ? { content: options } : options;
2320
- const result = await this.#client.postInteractionResponse(this.id, this.token, new InteractionResponse(InteractionResponseType.MessageUpdate, payload));
2321
- this.replied = true;
2322
- return result;
3110
+ return this.acknowledge(new InteractionResponse(InteractionResponseType.MessageUpdate, toMessageData(options)), "replied");
2323
3111
  }
2324
3112
  async showModal(modal) {
2325
- this.assertUnacknowledged();
2326
- const result = await this.#client.postInteractionResponse(this.id, this.token, new InteractionResponse(InteractionResponseType.Modal, modal));
2327
- this.replied = true;
2328
- return result;
3113
+ const data = "toJSON" in modal && typeof modal.toJSON === "function" ? modal.toJSON() : modal;
3114
+ return this.acknowledge(new InteractionResponse(InteractionResponseType.Modal, data), "replied");
2329
3115
  }
2330
3116
  }
2331
3117
 
@@ -2346,6 +3132,9 @@ class ComponentInteraction extends Interaction {
2346
3132
  get customId() {
2347
3133
  return this.data?.data?.custom_id ?? "";
2348
3134
  }
3135
+ get messageId() {
3136
+ return this.data?.message?.id;
3137
+ }
2349
3138
  get componentType() {
2350
3139
  return this.data?.data?.component_type ?? 0;
2351
3140
  }
@@ -2353,16 +3142,10 @@ class ComponentInteraction extends Interaction {
2353
3142
  return this.data?.data?.values ?? [];
2354
3143
  }
2355
3144
  async deferUpdate() {
2356
- this.assertUnacknowledged();
2357
- await this.postResponse(new InteractionResponse(InteractionResponseType.DeferredMessageUpdate));
2358
- this.deferred = true;
3145
+ await this.acknowledge(new InteractionResponse(InteractionResponseType.DeferredMessageUpdate), "deferred");
2359
3146
  }
2360
3147
  async update(options) {
2361
- this.assertUnacknowledged();
2362
- const payload = typeof options === "string" ? { content: options } : options;
2363
- const result = await this.postResponse(new InteractionResponse(InteractionResponseType.MessageUpdate, payload));
2364
- this.replied = true;
2365
- return result;
3148
+ return this.acknowledge(new InteractionResponse(InteractionResponseType.MessageUpdate, toMessageData(options)), "replied");
2366
3149
  }
2367
3150
  }
2368
3151
 
@@ -2405,8 +3188,7 @@ class AutocompleteInteraction extends Interaction {
2405
3188
  if (!Array.isArray(choices))
2406
3189
  throw new TypeError("Autocomplete choices must be an array.");
2407
3190
  const response = new InteractionResponse(InteractionResponseType.Autocomplete, { choices });
2408
- await this.postResponse(response);
2409
- this.replied = true;
3191
+ await this.acknowledge(response, "replied");
2410
3192
  }
2411
3193
  }
2412
3194
  function findFocused(options) {
@@ -2437,6 +3219,7 @@ function createInteraction(client, data) {
2437
3219
  }
2438
3220
 
2439
3221
  // packages/structures/src/index.ts
3222
+ var COMPONENT_COLLECTOR_DEFAULT_TIME = 15 * 60000;
2440
3223
  var NON_SYSTEM_MESSAGE_TYPES = new Set([0, 19, 20, 23]);
2441
3224
 
2442
3225
  class Message extends BaseStructure {
@@ -2457,6 +3240,7 @@ class Message extends BaseStructure {
2457
3240
  reference;
2458
3241
  components;
2459
3242
  referencedMessage;
3243
+ member;
2460
3244
  #context;
2461
3245
  constructor(data, context) {
2462
3246
  super(data.id);
@@ -2479,6 +3263,11 @@ class Message extends BaseStructure {
2479
3263
  this.reference = data.message_reference;
2480
3264
  this.referencedMessage = data.referenced_message ? new Message(data.referenced_message, context) : data.referenced_message === null ? null : undefined;
2481
3265
  this.#context = context;
3266
+ this.member = data.member && data.guild_id ? new GuildMember({
3267
+ ...data.member,
3268
+ user: data.member.user ?? data.author,
3269
+ guild_id: data.guild_id
3270
+ }, context) : null;
2482
3271
  this.channel = new Channel({ id: data.channel_id, type: 0, guild_id: data.guild_id }, context);
2483
3272
  }
2484
3273
  get embedsSuppressed() {
@@ -2519,6 +3308,20 @@ class Message extends BaseStructure {
2519
3308
  throw new Error("This message is not attached to a client.");
2520
3309
  return this.#context.crosspostMessage(this.channelId, this.id);
2521
3310
  }
3311
+ createComponentCollector(options = {}) {
3312
+ const collect = this.#context?.collectInteractions;
3313
+ if (!collect)
3314
+ throw new Error("This message is not attached to a client.");
3315
+ const { componentType, filter, ...rest } = options;
3316
+ return collect({
3317
+ ...rest,
3318
+ time: rest.time ?? (rest.idle ? undefined : COMPONENT_COLLECTOR_DEFAULT_TIME),
3319
+ filter: async (interaction) => interaction.isMessageComponent() && interaction.messageId === this.id && (componentType === undefined || interaction.componentType === componentType) && (filter ? await filter(interaction) : true)
3320
+ });
3321
+ }
3322
+ awaitComponent(options = {}) {
3323
+ return this.createComponentCollector({ ...options, max: 1 }).next();
3324
+ }
2522
3325
  react(emoji) {
2523
3326
  if (!this.#context?.addReaction)
2524
3327
  throw new Error("This message is not attached to a client.");
@@ -2592,23 +3395,43 @@ class Message extends BaseStructure {
2592
3395
  }
2593
3396
 
2594
3397
  // packages/managers/src/message.ts
3398
+ function toRequest(options) {
3399
+ const { files, ...body } = options;
3400
+ if (!files?.length)
3401
+ return body;
3402
+ return {
3403
+ body,
3404
+ files: files.map((file) => ({
3405
+ name: file.name,
3406
+ data: typeof file.data === "string" ? new TextEncoder().encode(file.data) : file.data,
3407
+ contentType: file.contentType
3408
+ }))
3409
+ };
3410
+ }
3411
+
2595
3412
  class MessageManager {
2596
- cache = new Collection;
3413
+ cache;
3414
+ #caching;
2597
3415
  #rest;
2598
3416
  #context;
2599
3417
  #channelId;
2600
- constructor(rest, context, channelId) {
3418
+ constructor(rest, context, channelId, cache) {
2601
3419
  if (!channelId)
2602
3420
  throw new TypeError("Channel ID is required.");
2603
3421
  this.#rest = rest;
2604
3422
  this.#context = context;
2605
3423
  this.#channelId = channelId;
3424
+ this.#caching = cache !== undefined;
3425
+ this.cache = new Collection(null, {
3426
+ ttl: cache?.ttl,
3427
+ maxSize: cache ? cache.maxSize ?? 100 : undefined
3428
+ });
2606
3429
  }
2607
3430
  async resolve(messageId) {
2608
3431
  return this.cache.get(messageId) ?? this.fetch(messageId);
2609
3432
  }
2610
3433
  async send(options) {
2611
- const data = await this.#rest.post(Routes.channelMessages(this.#channelId), options);
3434
+ const data = await this.#rest.post(Routes.channelMessages(this.#channelId), toRequest(options));
2612
3435
  return this.upsert(data);
2613
3436
  }
2614
3437
  async fetch(messageId) {
@@ -2619,13 +3442,14 @@ class MessageManager {
2619
3442
  return Promise.all(Array.from(messageIds, (messageId) => this.fetch(messageId)));
2620
3443
  }
2621
3444
  upsert(data) {
2622
- const existing = this.cache.get(data.id);
3445
+ const existing = this.cache.peek(data.id);
2623
3446
  const message = new Message(data, this.#context);
2624
3447
  if (existing) {
2625
3448
  Object.assign(existing, message);
2626
3449
  return existing;
2627
3450
  }
2628
- this.cache.set(message.id, message);
3451
+ if (this.#caching)
3452
+ this.cache.set(message.id, message);
2629
3453
  return message;
2630
3454
  }
2631
3455
  delete(messageId) {
@@ -2679,8 +3503,301 @@ class UserManager extends ResourceManager {
2679
3503
  });
2680
3504
  }
2681
3505
  }
3506
+ // packages/managers/src/emoji.ts
3507
+ class EmojiManager extends Manager {
3508
+ #rest;
3509
+ #guildId;
3510
+ constructor(rest, guildId) {
3511
+ super();
3512
+ this.#rest = rest;
3513
+ this.#guildId = guildId;
3514
+ }
3515
+ fetch(emojiId) {
3516
+ return this.fetchOnce(emojiId, async () => new Emoji(await this.#rest.get(Routes.guildEmoji(this.#guildId, emojiId))), (emoji) => this.#merge(emojiId, emoji));
3517
+ }
3518
+ async fetchAll() {
3519
+ const data = await this.#rest.get(Routes.guildEmoji(this.#guildId));
3520
+ return data.map((item) => this.upsert(item));
3521
+ }
3522
+ async create(options) {
3523
+ return this.upsert(await this.#rest.post(Routes.guildEmoji(this.#guildId), options));
3524
+ }
3525
+ async edit(emojiId, options) {
3526
+ return this.upsert(await this.#rest.patch(Routes.guildEmoji(this.#guildId, emojiId), options));
3527
+ }
3528
+ async deleteEmoji(emojiId) {
3529
+ await this.#rest.delete(Routes.guildEmoji(this.#guildId, emojiId));
3530
+ this.delete(emojiId);
3531
+ }
3532
+ upsert(data) {
3533
+ const key = data.id != null ? data.id : `unicode:${data.name ?? ""}`;
3534
+ return this.#merge(key, new Emoji(data));
3535
+ }
3536
+ #merge(key, emoji) {
3537
+ const existing = this.get(key);
3538
+ if (existing) {
3539
+ Object.assign(existing, emoji);
3540
+ return existing;
3541
+ }
3542
+ this.set(key, emoji);
3543
+ return emoji;
3544
+ }
3545
+ }
3546
+
3547
+ // packages/managers/src/advanced.ts
3548
+ function withQuery(path, query) {
3549
+ const params = new URLSearchParams;
3550
+ for (const [key, value] of Object.entries(query))
3551
+ if (value !== undefined)
3552
+ params.set(key, String(value));
3553
+ const suffix = params.toString();
3554
+ return suffix ? `${path}?${suffix}` : path;
3555
+ }
3556
+
3557
+ class GuildStickerManager extends Manager {
3558
+ #rest;
3559
+ guildId;
3560
+ constructor(rest, guildId) {
3561
+ super();
3562
+ this.#rest = rest;
3563
+ this.guildId = guildId;
3564
+ }
3565
+ #store(sticker) {
3566
+ this.set(sticker.id, sticker);
3567
+ return sticker;
3568
+ }
3569
+ async fetchAll() {
3570
+ const stickers = await this.#rest.get(Routes.guildSticker(this.guildId));
3571
+ this.clear();
3572
+ return stickers.map((sticker) => this.#store(sticker));
3573
+ }
3574
+ async fetch(stickerId) {
3575
+ return this.#store(await this.#rest.get(Routes.guildSticker(this.guildId, stickerId)));
3576
+ }
3577
+ async create(options) {
3578
+ const form = new FormData;
3579
+ form.set("name", options.name);
3580
+ form.set("description", options.description);
3581
+ form.set("tags", options.tags);
3582
+ form.set("file", options.file);
3583
+ return this.#store(await this.#rest.post(Routes.guildSticker(this.guildId), form, { reason: options.reason }));
3584
+ }
3585
+ async edit(stickerId, options) {
3586
+ const { reason, ...body } = options;
3587
+ return this.#store(await this.#rest.patch(Routes.guildSticker(this.guildId, stickerId), body, { reason }));
3588
+ }
3589
+ async remove(stickerId, reason) {
3590
+ await this.#rest.delete(Routes.guildSticker(this.guildId, stickerId), {
3591
+ reason
3592
+ });
3593
+ this.delete(stickerId);
3594
+ }
3595
+ sync(stickers) {
3596
+ this.clear();
3597
+ for (const sticker of stickers)
3598
+ this.#store(sticker);
3599
+ }
3600
+ }
3601
+
3602
+ class GuildSoundboardManager extends Manager {
3603
+ #rest;
3604
+ guildId;
3605
+ constructor(rest, guildId) {
3606
+ super();
3607
+ this.#rest = rest;
3608
+ this.guildId = guildId;
3609
+ }
3610
+ #store(sound) {
3611
+ this.set(sound.sound_id, sound);
3612
+ return sound;
3613
+ }
3614
+ async fetchAll() {
3615
+ const { items } = await this.#rest.get(Routes.guildSoundboardSound(this.guildId));
3616
+ this.clear();
3617
+ return items.map((sound) => this.#store(sound));
3618
+ }
3619
+ async fetch(soundId) {
3620
+ return this.#store(await this.#rest.get(Routes.guildSoundboardSound(this.guildId, soundId)));
3621
+ }
3622
+ async create(options) {
3623
+ if (options.volume !== undefined && (options.volume < 0 || options.volume > 1))
3624
+ throw new RangeError("Soundboard volume must be between 0 and 1.");
3625
+ return this.#store(await this.#rest.post(Routes.guildSoundboardSound(this.guildId), {
3626
+ name: options.name,
3627
+ sound: options.sound,
3628
+ volume: options.volume,
3629
+ emoji_id: options.emojiId,
3630
+ emoji_name: options.emojiName
3631
+ }, { reason: options.reason }));
3632
+ }
3633
+ async edit(soundId, options) {
3634
+ return this.#store(await this.#rest.patch(Routes.guildSoundboardSound(this.guildId, soundId), {
3635
+ name: options.name,
3636
+ volume: options.volume,
3637
+ emoji_id: options.emojiId,
3638
+ emoji_name: options.emojiName
3639
+ }, { reason: options.reason }));
3640
+ }
3641
+ async remove(soundId, reason) {
3642
+ await this.#rest.delete(Routes.guildSoundboardSound(this.guildId, soundId), { reason });
3643
+ this.delete(soundId);
3644
+ }
3645
+ }
3646
+
3647
+ class MonetizationManager extends Manager {
3648
+ #rest;
3649
+ applicationId;
3650
+ constructor(rest, applicationId) {
3651
+ super();
3652
+ this.#rest = rest;
3653
+ this.applicationId = applicationId;
3654
+ }
3655
+ fetchSkus() {
3656
+ return this.#rest.get(Routes.applicationSkus(this.applicationId));
3657
+ }
3658
+ async fetchEntitlements(query = {}) {
3659
+ if (query.limit !== undefined && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 100))
3660
+ throw new RangeError("Entitlement limit must be 1-100.");
3661
+ const entitlements = await this.#rest.get(withQuery(Routes.applicationEntitlement(this.applicationId), {
3662
+ user_id: query.userId,
3663
+ sku_ids: query.skuIds?.join(","),
3664
+ guild_id: query.guildId,
3665
+ before: query.before,
3666
+ after: query.after,
3667
+ limit: query.limit,
3668
+ exclude_ended: query.excludeEnded,
3669
+ exclude_deleted: query.excludeDeleted
3670
+ }));
3671
+ for (const entitlement of entitlements)
3672
+ this.set(entitlement.id, entitlement);
3673
+ return entitlements;
3674
+ }
3675
+ async fetch(entitlementId) {
3676
+ const entitlement = await this.#rest.get(Routes.applicationEntitlement(this.applicationId, entitlementId));
3677
+ this.set(entitlement.id, entitlement);
3678
+ return entitlement;
3679
+ }
3680
+ async consume(entitlementId) {
3681
+ await this.#rest.post(Routes.consumeEntitlement(this.applicationId, entitlementId));
3682
+ const cached = this.get(entitlementId);
3683
+ if (cached)
3684
+ cached.consumed = true;
3685
+ }
3686
+ async createTestEntitlement(options) {
3687
+ const entitlement = await this.#rest.post(Routes.applicationEntitlement(this.applicationId), {
3688
+ sku_id: options.skuId,
3689
+ owner_id: options.ownerId,
3690
+ owner_type: options.ownerType
3691
+ });
3692
+ this.set(entitlement.id, entitlement);
3693
+ return entitlement;
3694
+ }
3695
+ async deleteTestEntitlement(entitlementId) {
3696
+ await this.#rest.delete(Routes.applicationEntitlement(this.applicationId, entitlementId));
3697
+ this.delete(entitlementId);
3698
+ }
3699
+ fetchSubscriptions(skuId, query = {}) {
3700
+ return this.#rest.get(withQuery(Routes.skuSubscription(skuId), {
3701
+ user_id: query.userId,
3702
+ before: query.before,
3703
+ after: query.after,
3704
+ limit: query.limit
3705
+ }));
3706
+ }
3707
+ fetchSubscription(skuId, subscriptionId) {
3708
+ return this.#rest.get(Routes.skuSubscription(skuId, subscriptionId));
3709
+ }
3710
+ }
3711
+
3712
+ // packages/managers/src/member.ts
3713
+ class GuildMemberManager extends ResourceManager {
3714
+ #rest;
3715
+ #context;
3716
+ guildId;
3717
+ constructor(guildId, rest, context = () => {
3718
+ return;
3719
+ }) {
3720
+ super((id) => rest.get(Routes.guildMember(guildId, id)).then((data) => new GuildMember({ ...data, guild_id: guildId }, context())), (member) => member.user.id);
3721
+ this.guildId = guildId;
3722
+ this.#rest = rest;
3723
+ this.#context = context;
3724
+ }
3725
+ async kick(userId, reason) {
3726
+ await this.#rest.delete(Routes.guildMember(this.guildId, userId), {
3727
+ reason
3728
+ });
3729
+ this.delete(userId);
3730
+ }
3731
+ async ban(userId, options = {}) {
3732
+ await this.#rest.put(Routes.guildBan(this.guildId, userId), { delete_message_seconds: options.deleteMessageSeconds }, { reason: options.reason });
3733
+ this.delete(userId);
3734
+ }
3735
+ async unban(userId) {
3736
+ await this.#rest.delete(Routes.guildBan(this.guildId, userId));
3737
+ }
3738
+ async edit(userId, options, reason) {
3739
+ const data = await this.#rest.patch(Routes.guildMember(this.guildId, userId), options, { reason });
3740
+ const member = new GuildMember({ ...data, guild_id: this.guildId }, this.#context());
3741
+ this.set(member.user.id, member);
3742
+ return member;
3743
+ }
3744
+ async addRole(userId, roleId, reason) {
3745
+ await this.#rest.put(Routes.guildMemberRole(this.guildId, userId, roleId), undefined, { reason });
3746
+ }
3747
+ async removeRole(userId, roleId, reason) {
3748
+ await this.#rest.delete(Routes.guildMemberRole(this.guildId, userId, roleId), { reason });
3749
+ }
3750
+ async timeout(userId, milliseconds, reason) {
3751
+ const timeoutDate = milliseconds === null ? null : new Date(Date.now() + milliseconds).toISOString();
3752
+ return this.edit(userId, { communication_disabled_until: timeoutDate }, reason);
3753
+ }
3754
+ }
3755
+
3756
+ // packages/managers/src/role.ts
3757
+ class RoleManager extends ResourceManager {
3758
+ #rest;
3759
+ guildId;
3760
+ constructor(guildId, rest) {
3761
+ super((id) => rest.get(Routes.guildRole(guildId, id)).then((data) => new Role(data)), (role) => role.id);
3762
+ this.guildId = guildId;
3763
+ this.#rest = rest;
3764
+ }
3765
+ async fetchAll() {
3766
+ const data = await this.#rest.get(Routes.guildRoles(this.guildId));
3767
+ return data.map((item) => {
3768
+ const role = new Role(item);
3769
+ this.set(role.id, role);
3770
+ return role;
3771
+ });
3772
+ }
3773
+ async create(options) {
3774
+ const { reason, ...payload } = options;
3775
+ const data = await this.#rest.post(Routes.guildRoles(this.guildId), {
3776
+ ...payload,
3777
+ permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
3778
+ });
3779
+ const role = new Role(data);
3780
+ this.set(role.id, role);
3781
+ return role;
3782
+ }
3783
+ async edit(roleId, options) {
3784
+ const { reason, ...payload } = options;
3785
+ const data = await this.#rest.patch(Routes.guildRole(this.guildId, roleId), {
3786
+ ...payload,
3787
+ permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
3788
+ });
3789
+ const role = new Role(data);
3790
+ this.set(role.id, role);
3791
+ return role;
3792
+ }
3793
+ async deleteRole(roleId) {
3794
+ await this.#rest.delete(Routes.guildRole(this.guildId, roleId));
3795
+ this.delete(roleId);
3796
+ }
3797
+ }
3798
+
2682
3799
  // packages/managers/src/guild-resources.ts
2683
- function withQuery(path, params) {
3800
+ function withQuery2(path, params) {
2684
3801
  const query = new URLSearchParams;
2685
3802
  for (const [key, value] of Object.entries(params))
2686
3803
  if (value !== undefined)
@@ -2704,7 +3821,7 @@ class GuildBanManager extends Manager {
2704
3821
  }
2705
3822
  async fetchAll(options = {}) {
2706
3823
  const limit = options.limit === undefined ? undefined : Math.min(1000, Math.max(1, options.limit));
2707
- const bans = await this.#rest.get(withQuery(Routes.guildBans(this.guildId), {
3824
+ const bans = await this.#rest.get(withQuery2(Routes.guildBans(this.guildId), {
2708
3825
  limit,
2709
3826
  before: options.before,
2710
3827
  after: options.after
@@ -2737,12 +3854,12 @@ class GuildScheduledEventManager extends Manager {
2737
3854
  return event;
2738
3855
  }
2739
3856
  async fetch(eventId, options = {}) {
2740
- return this.#store(await this.#rest.get(withQuery(Routes.guildScheduledEvent(this.guildId, eventId), {
3857
+ return this.#store(await this.#rest.get(withQuery2(Routes.guildScheduledEvent(this.guildId, eventId), {
2741
3858
  with_user_count: options.withUserCount
2742
3859
  })));
2743
3860
  }
2744
3861
  async fetchAll(options = {}) {
2745
- const events = await this.#rest.get(withQuery(Routes.guildScheduledEvents(this.guildId), {
3862
+ const events = await this.#rest.get(withQuery2(Routes.guildScheduledEvents(this.guildId), {
2746
3863
  with_user_count: options.withUserCount
2747
3864
  }));
2748
3865
  return events.map((event) => this.#store(event));
@@ -2759,7 +3876,7 @@ class GuildScheduledEventManager extends Manager {
2759
3876
  }
2760
3877
  async fetchSubscribers(eventId, options = {}) {
2761
3878
  const limit = options.limit === undefined ? undefined : Math.min(100, Math.max(1, options.limit));
2762
- return this.#rest.get(withQuery(Routes.guildScheduledEventUsers(this.guildId, eventId), {
3879
+ return this.#rest.get(withQuery2(Routes.guildScheduledEventUsers(this.guildId, eventId), {
2763
3880
  limit,
2764
3881
  with_member: options.withMember,
2765
3882
  before: options.before,
@@ -2803,10 +3920,25 @@ class StageInstanceManager extends Manager {
2803
3920
 
2804
3921
  class PermissionOverwriteManager {
2805
3922
  #rest;
3923
+ #current;
2806
3924
  channelId;
2807
- constructor(rest, channelId) {
3925
+ constructor(rest, channelId, current = () => {
3926
+ return;
3927
+ }) {
2808
3928
  this.#rest = rest;
2809
3929
  this.channelId = channelId;
3930
+ this.#current = current;
3931
+ }
3932
+ async update(overwriteId, changes, options = {}) {
3933
+ const overwrites = this.#current() ?? (await this.#rest.get(Routes.channel(this.channelId))).permission_overwrites ?? [];
3934
+ const existing = overwrites.find((entry) => entry.id === overwriteId);
3935
+ const type = existing?.type ?? options.type;
3936
+ if (type !== 0 && type !== 1)
3937
+ throw new TypeError("A new permission overwrite needs a type: 0 for a role, 1 for a member.");
3938
+ const touched = (changes.allow ?? 0n) | (changes.deny ?? 0n) | (changes.inherit ?? 0n);
3939
+ const allow = BigInt(existing?.allow ?? 0) & ~touched | (changes.allow ?? 0n);
3940
+ const deny = BigInt(existing?.deny ?? 0) & ~touched | (changes.deny ?? 0n);
3941
+ await this.edit(overwriteId, { type, allow, deny }, options.reason);
2810
3942
  }
2811
3943
  async edit(overwriteId, options, reason) {
2812
3944
  await this.#rest.put(Routes.channelPermission(this.channelId, overwriteId), {
@@ -2821,7 +3953,7 @@ class PermissionOverwriteManager {
2821
3953
  }
2822
3954
 
2823
3955
  // packages/managers/src/guild.ts
2824
- function withQuery2(path, params) {
3956
+ function withQuery3(path, params) {
2825
3957
  const suffix = params.toString();
2826
3958
  return suffix ? `${path}?${suffix}` : path;
2827
3959
  }
@@ -2830,6 +3962,24 @@ class GuildManager extends ResourceManager {
2830
3962
  #rest;
2831
3963
  #bans = new Map;
2832
3964
  #scheduledEvents = new Map;
3965
+ #members = new Map;
3966
+ #roles = new Map;
3967
+ #emojis = new Map;
3968
+ #stickers = new Map;
3969
+ #soundboard = new Map;
3970
+ #voiceStates = new Map;
3971
+ #autoModerationRules = new Map;
3972
+ #invites = new Map;
3973
+ #context;
3974
+ attachContext(context) {
3975
+ this.#context = context;
3976
+ }
3977
+ #perGuild(map, guildId, create) {
3978
+ let manager = map.get(guildId);
3979
+ if (!manager)
3980
+ map.set(guildId, manager = create());
3981
+ return manager;
3982
+ }
2833
3983
  constructor(rest) {
2834
3984
  super(async (id) => new Guild(await rest.get(Routes.guild(id))), (guild) => guild.id);
2835
3985
  this.#rest = rest;
@@ -2846,6 +3996,68 @@ class GuildManager extends ResourceManager {
2846
3996
  this.#scheduledEvents.set(guildId, manager = new GuildScheduledEventManager(this.#rest, guildId));
2847
3997
  return manager;
2848
3998
  }
3999
+ members(guildId) {
4000
+ let manager = this.#members.get(guildId);
4001
+ if (!manager)
4002
+ this.#members.set(guildId, manager = new GuildMemberManager(guildId, this.#rest, () => this.#context));
4003
+ return manager;
4004
+ }
4005
+ roles(guildId) {
4006
+ let manager = this.#roles.get(guildId);
4007
+ if (!manager)
4008
+ this.#roles.set(guildId, manager = new RoleManager(guildId, this.#rest));
4009
+ return manager;
4010
+ }
4011
+ emojis(guildId) {
4012
+ let manager = this.#emojis.get(guildId);
4013
+ if (!manager)
4014
+ this.#emojis.set(guildId, manager = new EmojiManager(this.#rest, guildId));
4015
+ return manager;
4016
+ }
4017
+ stickers(guildId) {
4018
+ let manager = this.#stickers.get(guildId);
4019
+ if (!manager)
4020
+ this.#stickers.set(guildId, manager = new GuildStickerManager(this.#rest, guildId));
4021
+ return manager;
4022
+ }
4023
+ soundboard(guildId) {
4024
+ let manager = this.#soundboard.get(guildId);
4025
+ if (!manager)
4026
+ this.#soundboard.set(guildId, manager = new GuildSoundboardManager(this.#rest, guildId));
4027
+ return manager;
4028
+ }
4029
+ voiceStates(guildId) {
4030
+ return this.#perGuild(this.#voiceStates, guildId, () => new Manager);
4031
+ }
4032
+ autoModerationRules(guildId) {
4033
+ return this.#perGuild(this.#autoModerationRules, guildId, () => new Manager);
4034
+ }
4035
+ invites(guildId) {
4036
+ return this.#perGuild(this.#invites, guildId, () => new Manager);
4037
+ }
4038
+ patch(data) {
4039
+ const guild = new Guild(data);
4040
+ const existing = this.get(guild.id);
4041
+ if (!existing)
4042
+ return this.upsert(guild);
4043
+ for (const [key, value] of Object.entries(guild))
4044
+ if (value !== undefined)
4045
+ existing[key] = value;
4046
+ return existing;
4047
+ }
4048
+ delete(id) {
4049
+ this.#bans.delete(id);
4050
+ this.#scheduledEvents.delete(id);
4051
+ this.#members.delete(id);
4052
+ this.#roles.delete(id);
4053
+ this.#emojis.delete(id);
4054
+ this.#stickers.delete(id);
4055
+ this.#soundboard.delete(id);
4056
+ this.#voiceStates.delete(id);
4057
+ this.#autoModerationRules.delete(id);
4058
+ this.#invites.delete(id);
4059
+ return super.delete(id);
4060
+ }
2849
4061
  async create(options) {
2850
4062
  const data = await this.#rest.post("/guilds", options);
2851
4063
  return this.upsert(new Guild(data));
@@ -2881,7 +4093,7 @@ class GuildManager extends ResourceManager {
2881
4093
  params.set("after", options.after);
2882
4094
  if (options.limit !== undefined)
2883
4095
  params.set("limit", String(Math.min(100, Math.max(1, options.limit))));
2884
- return this.#rest.get(withQuery2(Routes.guildAuditLog(guildId), params));
4096
+ return this.#rest.get(withQuery3(Routes.guildAuditLog(guildId), params));
2885
4097
  }
2886
4098
  async fetchMembers(guildId, options = {}) {
2887
4099
  const params = new URLSearchParams;
@@ -2889,7 +4101,7 @@ class GuildManager extends ResourceManager {
2889
4101
  params.set("limit", String(Math.min(1000, Math.max(1, options.limit))));
2890
4102
  if (options.after)
2891
4103
  params.set("after", options.after);
2892
- return this.#rest.get(withQuery2(Routes.guildMembers(guildId), params));
4104
+ return this.#rest.get(withQuery3(Routes.guildMembers(guildId), params));
2893
4105
  }
2894
4106
  async fetchAutoModerationRules(guildId) {
2895
4107
  const rules = await this.#rest.get(Routes.guildAutoModerationRules(guildId));
@@ -2952,13 +4164,20 @@ class ApplicationCommandManager {
2952
4164
  }
2953
4165
 
2954
4166
  // packages/managers/src/index.ts
4167
+ var BULK_DELETE_MAX_AGE_MS = 14 * 24 * 60 * 60000;
4168
+ function snowflakeTime(id) {
4169
+ return Number((BigInt(id) >> 22n) + 1420070400000n);
4170
+ }
4171
+
2955
4172
  class ChannelManager extends Manager {
2956
4173
  #rest;
2957
4174
  #context;
2958
4175
  #messageManagers = new Map;
2959
- constructor(rest) {
4176
+ #messageCache;
4177
+ constructor(rest, options = {}) {
2960
4178
  super();
2961
4179
  this.#rest = rest;
4180
+ this.#messageCache = options.messageCache;
2962
4181
  this.#context = {
2963
4182
  sendMessage: (channelId, options) => this.send(channelId, options),
2964
4183
  editMessage: (channelId, messageId, options) => this.editMessage(channelId, messageId, options),
@@ -2977,27 +4196,29 @@ class ChannelManager extends Manager {
2977
4196
  messages(channelId) {
2978
4197
  let manager = this.#messageManagers.get(channelId);
2979
4198
  if (!manager) {
2980
- manager = new MessageManager(this.#rest, this.#context, channelId);
4199
+ manager = new MessageManager(this.#rest, this.#context, channelId, this.#messageCache);
2981
4200
  this.#messageManagers.set(channelId, manager);
2982
4201
  }
2983
4202
  return manager;
2984
4203
  }
2985
4204
  permissionOverwrites(channelId) {
2986
- return new PermissionOverwriteManager(this.#rest, channelId);
4205
+ return new PermissionOverwriteManager(this.#rest, channelId, () => this.get(channelId)?.permissionOverwrites);
2987
4206
  }
2988
4207
  threads(channelId) {
2989
4208
  return new ThreadManager(this.#rest, this.#context, channelId);
2990
4209
  }
2991
- async fetch(channelId) {
2992
- return this.upsert(await this.#rest.get(Routes.channel(channelId)));
4210
+ fetch(channelId) {
4211
+ return this.fetchOnce(channelId, async () => createChannel(await this.#rest.get(Routes.channel(channelId)), this.#context), (channel) => this.#merge(channel));
2993
4212
  }
2994
4213
  async resolve(channelId) {
2995
4214
  return this.get(channelId) ?? this.fetch(channelId);
2996
4215
  }
2997
4216
  upsert(data) {
2998
- const existing = this.get(data.id);
2999
- const channel = createChannel(data, this.#context);
3000
- if (existing) {
4217
+ return this.#merge(createChannel(data, this.#context));
4218
+ }
4219
+ #merge(channel) {
4220
+ const existing = this.get(channel.id);
4221
+ if (existing && existing.type === channel.type) {
3001
4222
  Object.assign(existing, channel);
3002
4223
  return existing;
3003
4224
  }
@@ -3007,6 +4228,37 @@ class ChannelManager extends Manager {
3007
4228
  update(channel) {
3008
4229
  return this.set(channel.id, channel);
3009
4230
  }
4231
+ deleteGuildChannels(guildId) {
4232
+ let removed = 0;
4233
+ for (const channel of this.values())
4234
+ if (channel.guildId === guildId && this.delete(channel.id))
4235
+ removed++;
4236
+ return removed;
4237
+ }
4238
+ async endPoll(channelId, messageId) {
4239
+ return this.messages(channelId).upsert(await this.#rest.post(Routes.pollExpire(channelId, messageId)));
4240
+ }
4241
+ async fetchPollVoters(channelId, messageId, answerId, options = {}) {
4242
+ if (options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100))
4243
+ throw new RangeError("Poll voter limit must be 1-100.");
4244
+ const params = new URLSearchParams;
4245
+ if (options.after)
4246
+ params.set("after", options.after);
4247
+ if (options.limit !== undefined)
4248
+ params.set("limit", String(options.limit));
4249
+ const suffix = params.toString();
4250
+ const { users } = await this.#rest.get(`${Routes.pollAnswerVoters(channelId, messageId, answerId)}${suffix ? `?${suffix}` : ""}`);
4251
+ return users.map((user) => new User(user));
4252
+ }
4253
+ async sendSoundboardSound(channelId, options) {
4254
+ await this.#rest.post(Routes.sendSoundboardSound(channelId), {
4255
+ sound_id: options.soundId,
4256
+ source_guild_id: options.sourceGuildId
4257
+ });
4258
+ }
4259
+ cachedMessages(channelId) {
4260
+ return this.#messageManagers.get(channelId);
4261
+ }
3010
4262
  async create(guildId, options) {
3011
4263
  return this.upsert(await this.#rest.post(Routes.guildChannels(guildId), options));
3012
4264
  }
@@ -3050,7 +4302,7 @@ class ChannelManager extends Manager {
3050
4302
  return this.messages(data.channel_id).upsert(data);
3051
4303
  }
3052
4304
  async editMessage(channelId, messageId, options) {
3053
- return this.messages(channelId).upsert(await this.#rest.patch(Routes.message(channelId, messageId), options));
4305
+ return this.messages(channelId).upsert(await this.#rest.patch(Routes.message(channelId, messageId), toRequest(options)));
3054
4306
  }
3055
4307
  async deleteMessage(channelId, messageId) {
3056
4308
  await this.#rest.delete(Routes.message(channelId, messageId));
@@ -3063,15 +4315,37 @@ class ChannelManager extends Manager {
3063
4315
  return this.messages(channelId).upsert(await this.#rest.post(Routes.crosspostMessage(channelId, messageId)));
3064
4316
  }
3065
4317
  async bulkDeleteMessages(channelId, messageIds) {
3066
- const ids = [...messageIds];
3067
- if (ids.length < 2 || ids.length > 100)
3068
- throw new RangeError("bulkDelete requires between 2 and 100 message IDs.");
4318
+ const ids = [...new Set(messageIds)];
4319
+ if (ids.length < 1 || ids.length > 100)
4320
+ throw new RangeError("bulkDelete requires between 1 and 100 message IDs.");
4321
+ if (ids.length === 1)
4322
+ return this.deleteMessage(channelId, ids[0]);
4323
+ const cutoff = Date.now() - BULK_DELETE_MAX_AGE_MS;
4324
+ const tooOld = ids.filter((id) => snowflakeTime(id) < cutoff);
4325
+ if (tooOld.length)
4326
+ throw new RangeError(`bulkDelete cannot delete messages older than 14 days: ${tooOld.join(", ")}`);
3069
4327
  await this.#rest.post(Routes.channelBulkDelete(channelId), {
3070
4328
  messages: ids
3071
4329
  });
3072
4330
  for (const id of ids)
3073
4331
  this.messages(channelId).delete(id);
3074
4332
  }
4333
+ async* iterateMessages(channelId, options = {}) {
4334
+ let before = options.before;
4335
+ let remaining = options.limit ?? Infinity;
4336
+ while (remaining > 0) {
4337
+ const page = await this.fetchMessages(channelId, {
4338
+ before,
4339
+ limit: Math.min(100, remaining)
4340
+ });
4341
+ for (const message of page)
4342
+ yield message;
4343
+ remaining -= page.length;
4344
+ if (page.length < 100)
4345
+ return;
4346
+ before = page.at(-1).id;
4347
+ }
4348
+ }
3075
4349
  async addReaction(channelId, messageId, emoji) {
3076
4350
  await this.#rest.put(`${Routes.messageReactions(channelId, messageId, emoji)}/@me`);
3077
4351
  }
@@ -3167,6 +4441,8 @@ class GatewaySession {
3167
4441
  return false;
3168
4442
  if (!Number.isInteger(sequence))
3169
4443
  return false;
4444
+ if (this.#sequence !== null && sequence < this.#sequence)
4445
+ return false;
3170
4446
  this.#sequence = sequence;
3171
4447
  return true;
3172
4448
  }
@@ -3265,8 +4541,11 @@ class GatewayHeartbeat {
3265
4541
  this.#clearBeatTimers();
3266
4542
  this.#interval = interval;
3267
4543
  this.#acknowledged = true;
3268
- this.#initialTimer = setTimeout(() => this.sendHeartbeat(), Math.random() * interval);
3269
- this.#timer = setInterval(() => this.sendHeartbeat(), interval);
4544
+ this.#initialTimer = setTimeout(() => {
4545
+ this.#initialTimer = undefined;
4546
+ this.sendHeartbeat();
4547
+ this.#timer = setInterval(() => this.sendHeartbeat(), interval);
4548
+ }, Math.random() * interval);
3270
4549
  }
3271
4550
  stop() {
3272
4551
  this.#clearBeatTimers();
@@ -3292,6 +4571,8 @@ class GatewayHeartbeat {
3292
4571
  }, this.#options.ackTimeout);
3293
4572
  }
3294
4573
  acknowledge() {
4574
+ if (this.#acknowledged)
4575
+ return;
3295
4576
  this.#acknowledged = true;
3296
4577
  this.#latency = this.#now() - this.#sentAt;
3297
4578
  this.#clearAckTimer();
@@ -3860,6 +5141,7 @@ class SendBudget {
3860
5141
  }
3861
5142
 
3862
5143
  // packages/ws/src/index.ts
5144
+ var RESUMABLE_CLOSE_CODE = 4900;
3863
5145
  var DEFAULT_GATEWAY_URL = "wss://gateway.discord.gg/?v=10&encoding=json";
3864
5146
 
3865
5147
  class Gateway {
@@ -3945,7 +5227,7 @@ class Gateway {
3945
5227
  } else {
3946
5228
  this.#emitError(new GatewayError(`Gateway heartbeat acknowledgement timed out after ${timeout.elapsedMs}ms.`));
3947
5229
  }
3948
- this.#transport.close(1001, timeout.type === "zombie" ? "Zombie Gateway connection" : "Heartbeat timeout");
5230
+ this.#transport.close(RESUMABLE_CLOSE_CODE, timeout.type === "zombie" ? "Zombie Gateway connection" : "Heartbeat timeout");
3949
5231
  }
3950
5232
  connect(url = DEFAULT_GATEWAY_URL) {
3951
5233
  if (this.state === "CLOSED" /* Closed */)
@@ -4081,7 +5363,7 @@ class Gateway {
4081
5363
  this.#emit("heartbeatAck", action.data);
4082
5364
  return;
4083
5365
  case "reconnect":
4084
- this.#transport.close(1001, "Server requested reconnect");
5366
+ this.#transport.close(RESUMABLE_CLOSE_CODE, "Server requested reconnect");
4085
5367
  return;
4086
5368
  case "invalid-session": {
4087
5369
  if (!action.resumable)
@@ -4275,6 +5557,7 @@ class Client extends EventEmitter2 {
4275
5557
  channels;
4276
5558
  stageInstances;
4277
5559
  application;
5560
+ monetization;
4278
5561
  get ws() {
4279
5562
  return this.#gateway;
4280
5563
  }
@@ -4306,6 +5589,7 @@ class Client extends EventEmitter2 {
4306
5589
  return this.#gateway.requestGuildMembers(data);
4307
5590
  }
4308
5591
  #gateway;
5592
+ #cache;
4309
5593
  #resourceContext;
4310
5594
  constructor(options) {
4311
5595
  super();
@@ -4313,9 +5597,18 @@ class Client extends EventEmitter2 {
4313
5597
  if (!options.token?.trim())
4314
5598
  throw new TypeError("Client token is required.");
4315
5599
  this.rest = new REST({ token: options.token, ...options.rest });
5600
+ this.#cache = {
5601
+ users: true,
5602
+ members: true,
5603
+ roles: true,
5604
+ emojis: true,
5605
+ ...options.cache
5606
+ };
4316
5607
  this.users = new UserManager(this.rest);
4317
5608
  this.guilds = new GuildManager(this.rest);
4318
- this.channels = new ChannelManager(this.rest);
5609
+ this.channels = new ChannelManager(this.rest, {
5610
+ messageCache: options.messageCache
5611
+ });
4319
5612
  this.stageInstances = new StageInstanceManager(this.rest);
4320
5613
  const placeholderAppCommands = new ApplicationCommandManager(this.rest, "0");
4321
5614
  this.application = { commands: placeholderAppCommands };
@@ -4331,8 +5624,32 @@ class Client extends EventEmitter2 {
4331
5624
  removeReaction: (channelId, messageId, emoji, userId) => this.channels.removeReaction(channelId, messageId, emoji, userId),
4332
5625
  removeAllReactions: (channelId, messageId) => this.channels.removeAllReactions(channelId, messageId),
4333
5626
  pinMessage: (channelId, messageId) => this.channels.pinMessage(channelId, messageId),
4334
- unpinMessage: (channelId, messageId) => this.channels.unpinMessage(channelId, messageId)
5627
+ unpinMessage: (channelId, messageId) => this.channels.unpinMessage(channelId, messageId),
5628
+ collectInteractions: (options) => this.createCollector("interactionCreate" /* InteractionCreate */, options),
5629
+ memberPermissions: (guildId, memberId, roleIds, channelId) => this.#memberPermissions(guildId, memberId, roleIds, channelId),
5630
+ kickMember: (guildId, userId, reason) => this.guilds.members(guildId).kick(userId, reason),
5631
+ banMember: (guildId, userId, options) => this.guilds.members(guildId).ban(userId, options),
5632
+ editMember: (guildId, userId, options, reason) => this.guilds.members(guildId).edit(userId, options, reason),
5633
+ addMemberRole: (guildId, userId, roleId, reason) => this.guilds.members(guildId).addRole(userId, roleId, reason),
5634
+ removeMemberRole: (guildId, userId, roleId, reason) => this.guilds.members(guildId).removeRole(userId, roleId, reason),
5635
+ editPermissionOverwrite: async (channelId, targetId, changes, options) => {
5636
+ const bits = { allow: 0n, deny: 0n, inherit: 0n };
5637
+ for (const [name, value] of Object.entries(changes)) {
5638
+ if (!/^[A-Za-z]+$/.test(name))
5639
+ throw new TypeError(`Unknown permission: ${name}`);
5640
+ let bit;
5641
+ try {
5642
+ bit = new PermissionSet(name).bitfield;
5643
+ } catch {
5644
+ throw new TypeError(`Unknown permission: ${name}`);
5645
+ }
5646
+ const key = value === true ? "allow" : value === false ? "deny" : "inherit";
5647
+ bits[key] |= bit;
5648
+ }
5649
+ return this.channels.permissionOverwrites(channelId).update(targetId, bits, options);
5650
+ }
4335
5651
  };
5652
+ this.guilds.attachContext(this.#resourceContext);
4336
5653
  this.#gateway = new Gateway({
4337
5654
  token: options.token,
4338
5655
  intents: options.intents,
@@ -4346,6 +5663,8 @@ class Client extends EventEmitter2 {
4346
5663
  this.state = "ready";
4347
5664
  const appId = ready.application?.id ?? this.user.id;
4348
5665
  this.application.commands = new ApplicationCommandManager(this.rest, appId);
5666
+ if (this.monetization?.applicationId !== appId)
5667
+ this.monetization = new MonetizationManager(this.rest, appId);
4349
5668
  this.emit("ready" /* Ready */, this.user);
4350
5669
  });
4351
5670
  this.#gateway.on("RESUMED", () => {
@@ -4362,19 +5681,46 @@ class Client extends EventEmitter2 {
4362
5681
  this.emit("close" /* Close */, data);
4363
5682
  });
4364
5683
  this.#gateway.on("MESSAGE_CREATE", (data) => {
4365
- const message = new Message(data, this.#resourceContext);
4366
- this.channels.set(message.channelId, message.channel);
4367
- this.users.set(message.author.id, message.author);
4368
- this.emit("messageCreate" /* MessageCreate */, message);
5684
+ const payload = data;
5685
+ const message = new Message(payload, this.#resourceContext);
5686
+ this.#observeMessage(message);
5687
+ if (payload.member && payload.guild_id && this.guilds.has(payload.guild_id))
5688
+ this.#upsertMember(payload.guild_id, {
5689
+ ...payload.member,
5690
+ user: payload.member.user ?? payload.author
5691
+ });
5692
+ const cached = this.options.messageCache ? this.channels.messages(message.channelId).upsert(data) : message;
5693
+ this.emit("messageCreate" /* MessageCreate */, cached);
4369
5694
  });
4370
5695
  this.#gateway.on("MESSAGE_UPDATE", (data) => {
4371
5696
  const message = new Message(data, this.#resourceContext);
4372
- this.channels.set(message.channelId, message.channel);
4373
- this.users.set(message.author.id, message.author);
4374
- this.emit("messageUpdate" /* MessageUpdate */, message);
5697
+ this.#observeMessage(message);
5698
+ const messages = this.channels.cachedMessages(message.channelId);
5699
+ const previous = messages?.cache.peek(message.id);
5700
+ if (previous)
5701
+ messages.cache.set(message.id, message);
5702
+ this.emit("messageUpdate" /* MessageUpdate */, message, previous);
5703
+ });
5704
+ this.#gateway.on("MESSAGE_DELETE", (data) => {
5705
+ const payload = data;
5706
+ const messages = this.channels.cachedMessages(payload.channel_id);
5707
+ const removed = messages?.cache.peek(payload.id);
5708
+ messages?.delete(payload.id);
5709
+ this.emit("messageDelete" /* MessageDelete */, payload, removed);
5710
+ });
5711
+ this.#gateway.on("MESSAGE_DELETE_BULK", (data) => {
5712
+ const payload = data;
5713
+ const messages = this.channels.cachedMessages(payload.channel_id);
5714
+ const removed = [];
5715
+ if (messages)
5716
+ for (const id of payload.ids) {
5717
+ const message = messages.cache.peek(id);
5718
+ if (message)
5719
+ removed.push(message);
5720
+ messages.delete(id);
5721
+ }
5722
+ this.emit("messageDeleteBulk" /* MessageDeleteBulk */, payload, removed);
4375
5723
  });
4376
- this.#gateway.on("MESSAGE_DELETE", (data) => this.emit("messageDelete" /* MessageDelete */, data));
4377
- this.#gateway.on("MESSAGE_DELETE_BULK", (data) => this.emit("messageDeleteBulk" /* MessageDeleteBulk */, data));
4378
5724
  this.#gateway.on("MESSAGE_REACTION_ADD", (data) => this.emit("messageReactionAdd" /* MessageReactionAdd */, data));
4379
5725
  this.#gateway.on("MESSAGE_REACTION_REMOVE", (data) => this.emit("messageReactionRemove" /* MessageReactionRemove */, data));
4380
5726
  this.#gateway.on("MESSAGE_REACTION_REMOVE_ALL", (data) => this.emit("messageReactionRemoveAll" /* MessageReactionRemoveAll */, data));
@@ -4388,20 +5734,27 @@ class Client extends EventEmitter2 {
4388
5734
  return;
4389
5735
  }
4390
5736
  const wasCached = this.guilds.has(payload.id);
4391
- const guild = new Guild(payload);
4392
- this.guilds.set(guild.id, guild);
5737
+ this.guilds.patch(payload);
5738
+ for (const role of payload.roles ?? [])
5739
+ this.#upsertRole(payload.id, role);
5740
+ if (this.#cache.emojis) {
5741
+ const emojis = this.guilds.emojis(payload.id);
5742
+ for (const emoji of payload.emojis ?? [])
5743
+ emojis.upsert(emoji);
5744
+ }
4393
5745
  for (const member of payload.members ?? [])
4394
- this.users.set(member.user.id, new User(member.user));
5746
+ this.#upsertMember(payload.id, member);
5747
+ for (const state of payload.voice_states ?? [])
5748
+ this.#storeVoiceState(payload.id, state);
4395
5749
  for (const channelData of [
4396
5750
  ...payload.channels ?? [],
4397
5751
  ...payload.threads ?? []
4398
5752
  ])
4399
- this.channels.set(channelData.id, createChannel(channelData, this.#resourceContext));
5753
+ this.channels.upsert({ ...channelData, guild_id: payload.id });
4400
5754
  this.emit(wasCached ? "guildAvailable" /* GuildAvailable */ : "guildCreate" /* GuildCreate */, payload);
4401
5755
  });
4402
5756
  this.#gateway.on("GUILD_UPDATE", (data) => {
4403
- const guild = new Guild(data);
4404
- this.guilds.update(guild);
5757
+ this.guilds.patch(data);
4405
5758
  this.emit("guildUpdate" /* GuildUpdate */, data);
4406
5759
  });
4407
5760
  this.#gateway.on("GUILD_DELETE", (data) => {
@@ -4411,45 +5764,158 @@ class Client extends EventEmitter2 {
4411
5764
  return;
4412
5765
  }
4413
5766
  this.guilds.delete(payload.id);
5767
+ this.channels.deleteGuildChannels(payload.id);
4414
5768
  this.emit("guildDelete" /* GuildDelete */, payload);
4415
5769
  });
4416
5770
  this.#gateway.on("GUILD_MEMBER_ADD", (data) => {
4417
5771
  const member = data;
4418
- this.users.set(member.user.id, new User(member.user));
5772
+ this.#upsertMember(member.guild_id, member);
4419
5773
  this.emit("guildMemberAdd" /* GuildMemberAdd */, member);
4420
5774
  });
4421
5775
  this.#gateway.on("GUILD_MEMBER_UPDATE", (data) => {
4422
5776
  const member = data;
4423
- this.users.set(member.user.id, new User(member.user));
5777
+ this.#upsertMember(member.guild_id, member);
4424
5778
  this.emit("guildMemberUpdate" /* GuildMemberUpdate */, member);
4425
5779
  });
4426
- this.#gateway.on("GUILD_MEMBER_REMOVE", (data) => this.emit("guildMemberRemove" /* GuildMemberRemove */, data));
4427
- this.#gateway.on("GUILD_MEMBERS_CHUNK", (data) => this.emit("guildMembersChunk" /* GuildMembersChunk */, data));
4428
- this.#gateway.on("GUILD_BAN_ADD", (data) => this.emit("guildBanAdd" /* GuildBanAdd */, data));
4429
- this.#gateway.on("GUILD_BAN_REMOVE", (data) => this.emit("guildBanRemove" /* GuildBanRemove */, data));
4430
- this.#gateway.on("GUILD_ROLE_CREATE", (data) => this.emit("guildRoleCreate" /* GuildRoleCreate */, data));
4431
- this.#gateway.on("GUILD_ROLE_UPDATE", (data) => this.emit("guildRoleUpdate" /* GuildRoleUpdate */, data));
4432
- this.#gateway.on("GUILD_ROLE_DELETE", (data) => this.emit("guildRoleDelete" /* GuildRoleDelete */, data));
4433
- this.#gateway.on("GUILD_EMOJIS_UPDATE", (data) => this.emit("guildEmojisUpdate" /* GuildEmojisUpdate */, data));
4434
- this.#gateway.on("GUILD_STICKERS_UPDATE", (data) => this.emit("guildStickersUpdate" /* GuildStickersUpdate */, data));
5780
+ this.#gateway.on("GUILD_MEMBER_REMOVE", (data) => {
5781
+ const member = data;
5782
+ this.guilds.members(member.guild_id).delete(member.user.id);
5783
+ this.emit("guildMemberRemove" /* GuildMemberRemove */, member);
5784
+ });
5785
+ this.#gateway.on("GUILD_MEMBERS_CHUNK", (data) => {
5786
+ const chunk = data;
5787
+ for (const member of chunk.members)
5788
+ this.#upsertMember(chunk.guild_id, member);
5789
+ this.emit("guildMembersChunk" /* GuildMembersChunk */, chunk);
5790
+ });
5791
+ this.#gateway.on("GUILD_BAN_ADD", (data) => {
5792
+ const ban = data;
5793
+ const bans = this.guilds.bans(ban.guild_id);
5794
+ bans.set(ban.user.id, {
5795
+ reason: bans.get(ban.user.id)?.reason ?? null,
5796
+ user: ban.user
5797
+ });
5798
+ this.guilds.members(ban.guild_id).delete(ban.user.id);
5799
+ this.emit("guildBanAdd" /* GuildBanAdd */, ban);
5800
+ });
5801
+ this.#gateway.on("GUILD_BAN_REMOVE", (data) => {
5802
+ const ban = data;
5803
+ this.guilds.bans(ban.guild_id).delete(ban.user.id);
5804
+ this.emit("guildBanRemove" /* GuildBanRemove */, ban);
5805
+ });
5806
+ this.#gateway.on("GUILD_ROLE_CREATE", (data) => {
5807
+ const event = data;
5808
+ this.#upsertRole(event.guild_id, event.role);
5809
+ this.emit("guildRoleCreate" /* GuildRoleCreate */, event);
5810
+ });
5811
+ this.#gateway.on("GUILD_ROLE_UPDATE", (data) => {
5812
+ const event = data;
5813
+ this.#upsertRole(event.guild_id, event.role);
5814
+ this.emit("guildRoleUpdate" /* GuildRoleUpdate */, event);
5815
+ });
5816
+ this.#gateway.on("GUILD_ROLE_DELETE", (data) => {
5817
+ const event = data;
5818
+ this.guilds.roles(event.guild_id).delete(event.role_id);
5819
+ this.emit("guildRoleDelete" /* GuildRoleDelete */, event);
5820
+ });
5821
+ this.#gateway.on("GUILD_EMOJIS_UPDATE", (data) => {
5822
+ const event = data;
5823
+ if (this.#cache.emojis) {
5824
+ const emojis = this.guilds.emojis(event.guild_id);
5825
+ const current = new Set(event.emojis.map((emoji) => emoji.id));
5826
+ for (const id of [...emojis.cache.keys()])
5827
+ if (!current.has(id))
5828
+ emojis.delete(id);
5829
+ for (const emoji of event.emojis)
5830
+ emojis.upsert(emoji);
5831
+ }
5832
+ this.emit("guildEmojisUpdate" /* GuildEmojisUpdate */, event);
5833
+ });
5834
+ this.#gateway.on("GUILD_STICKERS_UPDATE", (data) => {
5835
+ const event = data;
5836
+ this.guilds.stickers(event.guild_id).sync(event.stickers);
5837
+ this.emit("guildStickersUpdate" /* GuildStickersUpdate */, event);
5838
+ });
5839
+ this.#gateway.on("GUILD_SOUNDBOARD_SOUND_CREATE", (data) => {
5840
+ const sound = data;
5841
+ if (sound.guild_id)
5842
+ this.guilds.soundboard(sound.guild_id).set(sound.sound_id, sound);
5843
+ this.emit("soundboardSoundCreate" /* SoundboardSoundCreate */, sound);
5844
+ });
5845
+ this.#gateway.on("GUILD_SOUNDBOARD_SOUND_UPDATE", (data) => {
5846
+ const sound = data;
5847
+ if (sound.guild_id)
5848
+ this.guilds.soundboard(sound.guild_id).set(sound.sound_id, sound);
5849
+ this.emit("soundboardSoundUpdate" /* SoundboardSoundUpdate */, sound);
5850
+ });
5851
+ this.#gateway.on("GUILD_SOUNDBOARD_SOUND_DELETE", (data) => {
5852
+ const event = data;
5853
+ this.guilds.soundboard(event.guild_id).delete(event.sound_id);
5854
+ this.emit("soundboardSoundDelete" /* SoundboardSoundDelete */, event);
5855
+ });
5856
+ this.#gateway.on("GUILD_SOUNDBOARD_SOUNDS_UPDATE", (data) => {
5857
+ const event = data;
5858
+ const sounds = this.guilds.soundboard(event.guild_id);
5859
+ sounds.clear();
5860
+ for (const sound of event.soundboard_sounds)
5861
+ sounds.set(sound.sound_id, sound);
5862
+ this.emit("soundboardSoundsUpdate" /* SoundboardSoundsUpdate */, event);
5863
+ });
5864
+ this.#gateway.on("ENTITLEMENT_CREATE", (data) => {
5865
+ const entitlement = data;
5866
+ this.monetization?.set(entitlement.id, entitlement);
5867
+ this.emit("entitlementCreate" /* EntitlementCreate */, entitlement);
5868
+ });
5869
+ this.#gateway.on("ENTITLEMENT_UPDATE", (data) => {
5870
+ const entitlement = data;
5871
+ this.monetization?.set(entitlement.id, entitlement);
5872
+ this.emit("entitlementUpdate" /* EntitlementUpdate */, entitlement);
5873
+ });
5874
+ this.#gateway.on("ENTITLEMENT_DELETE", (data) => {
5875
+ const entitlement = data;
5876
+ this.monetization?.delete(entitlement.id);
5877
+ this.emit("entitlementDelete" /* EntitlementDelete */, entitlement);
5878
+ });
4435
5879
  this.#gateway.on("GUILD_INTEGRATIONS_UPDATE", (data) => this.emit("guildIntegrationsUpdate" /* GuildIntegrationsUpdate */, data));
4436
- this.#gateway.on("GUILD_SCHEDULED_EVENT_CREATE", (data) => this.emit("guildScheduledEventCreate" /* GuildScheduledEventCreate */, data));
4437
- this.#gateway.on("GUILD_SCHEDULED_EVENT_UPDATE", (data) => this.emit("guildScheduledEventUpdate" /* GuildScheduledEventUpdate */, data));
4438
- this.#gateway.on("GUILD_SCHEDULED_EVENT_DELETE", (data) => this.emit("guildScheduledEventDelete" /* GuildScheduledEventDelete */, data));
5880
+ this.#gateway.on("GUILD_SCHEDULED_EVENT_CREATE", (data) => {
5881
+ const event = data;
5882
+ this.guilds.scheduledEvents(event.guild_id).set(event.id, event);
5883
+ this.emit("guildScheduledEventCreate" /* GuildScheduledEventCreate */, event);
5884
+ });
5885
+ this.#gateway.on("GUILD_SCHEDULED_EVENT_UPDATE", (data) => {
5886
+ const event = data;
5887
+ this.guilds.scheduledEvents(event.guild_id).set(event.id, event);
5888
+ this.emit("guildScheduledEventUpdate" /* GuildScheduledEventUpdate */, event);
5889
+ });
5890
+ this.#gateway.on("GUILD_SCHEDULED_EVENT_DELETE", (data) => {
5891
+ const event = data;
5892
+ this.guilds.scheduledEvents(event.guild_id).delete(event.id);
5893
+ this.emit("guildScheduledEventDelete" /* GuildScheduledEventDelete */, event);
5894
+ });
4439
5895
  this.#gateway.on("GUILD_SCHEDULED_EVENT_USER_ADD", (data) => this.emit("guildScheduledEventUserAdd" /* GuildScheduledEventUserAdd */, data));
4440
5896
  this.#gateway.on("GUILD_SCHEDULED_EVENT_USER_REMOVE", (data) => this.emit("guildScheduledEventUserRemove" /* GuildScheduledEventUserRemove */, data));
4441
- this.#gateway.on("AUTO_MODERATION_RULE_CREATE", (data) => this.emit("autoModerationRuleCreate" /* AutoModerationRuleCreate */, data));
4442
- this.#gateway.on("AUTO_MODERATION_RULE_UPDATE", (data) => this.emit("autoModerationRuleUpdate" /* AutoModerationRuleUpdate */, data));
4443
- this.#gateway.on("AUTO_MODERATION_RULE_DELETE", (data) => this.emit("autoModerationRuleDelete" /* AutoModerationRuleDelete */, data));
5897
+ this.#gateway.on("AUTO_MODERATION_RULE_CREATE", (data) => {
5898
+ const rule = data;
5899
+ this.guilds.autoModerationRules(rule.guild_id).set(rule.id, rule);
5900
+ this.emit("autoModerationRuleCreate" /* AutoModerationRuleCreate */, rule);
5901
+ });
5902
+ this.#gateway.on("AUTO_MODERATION_RULE_UPDATE", (data) => {
5903
+ const rule = data;
5904
+ this.guilds.autoModerationRules(rule.guild_id).set(rule.id, rule);
5905
+ this.emit("autoModerationRuleUpdate" /* AutoModerationRuleUpdate */, rule);
5906
+ });
5907
+ this.#gateway.on("AUTO_MODERATION_RULE_DELETE", (data) => {
5908
+ const rule = data;
5909
+ this.guilds.autoModerationRules(rule.guild_id).delete(rule.id);
5910
+ this.emit("autoModerationRuleDelete" /* AutoModerationRuleDelete */, rule);
5911
+ });
4444
5912
  this.#gateway.on("AUTO_MODERATION_ACTION_EXECUTION", (data) => this.emit("autoModerationActionExecution" /* AutoModerationActionExecution */, data));
4445
5913
  this.#gateway.on("CHANNEL_CREATE", (data) => {
4446
- const channel = createChannel(data, this.#resourceContext);
4447
- this.channels.update(channel);
5914
+ const channel = this.channels.upsert(data);
4448
5915
  this.emit("channelCreate" /* ChannelCreate */, channel);
4449
5916
  });
4450
5917
  this.#gateway.on("CHANNEL_UPDATE", (data) => {
4451
- const channel = createChannel(data, this.#resourceContext);
4452
- this.channels.update(channel);
5918
+ const channel = this.channels.upsert(data);
4453
5919
  this.emit("channelUpdate" /* ChannelUpdate */, channel);
4454
5920
  });
4455
5921
  this.#gateway.on("CHANNEL_DELETE", (data) => {
@@ -4459,13 +5925,11 @@ class Client extends EventEmitter2 {
4459
5925
  });
4460
5926
  this.#gateway.on("CHANNEL_PINS_UPDATE", (data) => this.emit("channelPinsUpdate" /* ChannelPinsUpdate */, data));
4461
5927
  this.#gateway.on("THREAD_CREATE", (data) => {
4462
- const channel = createChannel(data, this.#resourceContext);
4463
- this.channels.update(channel);
5928
+ const channel = this.channels.upsert(data);
4464
5929
  this.emit("threadCreate" /* ThreadCreate */, channel);
4465
5930
  });
4466
5931
  this.#gateway.on("THREAD_UPDATE", (data) => {
4467
- const channel = createChannel(data, this.#resourceContext);
4468
- this.channels.update(channel);
5932
+ const channel = this.channels.upsert(data);
4469
5933
  this.emit("threadUpdate" /* ThreadUpdate */, channel);
4470
5934
  });
4471
5935
  this.#gateway.on("THREAD_DELETE", (data) => {
@@ -4473,16 +5937,48 @@ class Client extends EventEmitter2 {
4473
5937
  this.channels.delete(payload.id);
4474
5938
  this.emit("threadDelete" /* ThreadDelete */, payload);
4475
5939
  });
4476
- this.#gateway.on("THREAD_LIST_SYNC", (data) => this.emit("threadListSync" /* ThreadListSync */, data));
5940
+ this.#gateway.on("THREAD_LIST_SYNC", (data) => {
5941
+ const sync = data;
5942
+ for (const thread of sync.threads)
5943
+ this.channels.upsert({ ...thread, guild_id: sync.guild_id });
5944
+ this.emit("threadListSync" /* ThreadListSync */, sync);
5945
+ });
4477
5946
  this.#gateway.on("THREAD_MEMBERS_UPDATE", (data) => this.emit("threadMembersUpdate" /* ThreadMembersUpdate */, data));
4478
5947
  this.#gateway.on("THREAD_MEMBER_UPDATE", (data) => this.emit("threadMemberUpdate" /* ThreadMemberUpdate */, data));
4479
- this.#gateway.on("STAGE_INSTANCE_CREATE", (data) => this.emit("stageInstanceCreate" /* StageInstanceCreate */, data));
4480
- this.#gateway.on("STAGE_INSTANCE_UPDATE", (data) => this.emit("stageInstanceUpdate" /* StageInstanceUpdate */, data));
4481
- this.#gateway.on("STAGE_INSTANCE_DELETE", (data) => this.emit("stageInstanceDelete" /* StageInstanceDelete */, data));
4482
- this.#gateway.on("INVITE_CREATE", (data) => this.emit("inviteCreate" /* InviteCreate */, data));
4483
- this.#gateway.on("INVITE_DELETE", (data) => this.emit("inviteDelete" /* InviteDelete */, data));
5948
+ this.#gateway.on("STAGE_INSTANCE_CREATE", (data) => {
5949
+ const stage = data;
5950
+ this.stageInstances.set(stage.channel_id, stage);
5951
+ this.emit("stageInstanceCreate" /* StageInstanceCreate */, stage);
5952
+ });
5953
+ this.#gateway.on("STAGE_INSTANCE_UPDATE", (data) => {
5954
+ const stage = data;
5955
+ this.stageInstances.set(stage.channel_id, stage);
5956
+ this.emit("stageInstanceUpdate" /* StageInstanceUpdate */, stage);
5957
+ });
5958
+ this.#gateway.on("STAGE_INSTANCE_DELETE", (data) => {
5959
+ const stage = data;
5960
+ this.stageInstances.delete(stage.channel_id);
5961
+ this.emit("stageInstanceDelete" /* StageInstanceDelete */, stage);
5962
+ });
5963
+ this.#gateway.on("INVITE_CREATE", (data) => {
5964
+ const invite = data;
5965
+ if (invite.guild_id)
5966
+ this.guilds.invites(invite.guild_id).set(invite.code, invite);
5967
+ this.emit("inviteCreate" /* InviteCreate */, invite);
5968
+ });
5969
+ this.#gateway.on("INVITE_DELETE", (data) => {
5970
+ const invite = data;
5971
+ if (invite.guild_id)
5972
+ this.guilds.invites(invite.guild_id).delete(invite.code);
5973
+ this.emit("inviteDelete" /* InviteDelete */, invite);
5974
+ });
4484
5975
  this.#gateway.on("WEBHOOKS_UPDATE", (data) => this.emit("webhooksUpdate" /* WebhooksUpdate */, data));
4485
- this.#gateway.on("VOICE_STATE_UPDATE", (data) => this.emit("voiceStateUpdate" /* VoiceStateUpdate */, data));
5976
+ this.#gateway.on("VOICE_STATE_UPDATE", (data) => {
5977
+ const state = data;
5978
+ if (state.guild_id)
5979
+ this.#storeVoiceState(state.guild_id, state);
5980
+ this.emit("voiceStateUpdate" /* VoiceStateUpdate */, state);
5981
+ });
4486
5982
  this.#gateway.on("VOICE_SERVER_UPDATE", (data) => this.emit("voiceServerUpdate" /* VoiceServerUpdate */, data));
4487
5983
  this.#gateway.on("PRESENCE_UPDATE", (data) => this.emit("presenceUpdate" /* PresenceUpdate */, data));
4488
5984
  this.#gateway.on("TYPING_START", (data) => this.emit("typingStart" /* TypingStart */, data));
@@ -4490,6 +5986,103 @@ class Client extends EventEmitter2 {
4490
5986
  this.#gateway.on("RAW", (data) => this.emit("raw" /* Raw */, data));
4491
5987
  this.#gateway.on("error", (error) => this.emit("error" /* Error */, error));
4492
5988
  }
5989
+ #observeMessage(message) {
5990
+ if (!this.channels.has(message.channelId))
5991
+ this.channels.set(message.channelId, message.channel);
5992
+ if (this.#cache.users)
5993
+ this.#merge(this.users, message.author.id, message.author);
5994
+ }
5995
+ #upsertMember(guildId, data) {
5996
+ const member = new GuildMember({ ...data, guild_id: guildId }, this.#resourceContext);
5997
+ if (this.#cache.users)
5998
+ this.#merge(this.users, member.user.id, member.user);
5999
+ if (!this.#cache.members)
6000
+ return member;
6001
+ return this.#merge(this.guilds.members(guildId), member.user.id, member);
6002
+ }
6003
+ #storeVoiceState(guildId, state) {
6004
+ const states = this.guilds.voiceStates(guildId);
6005
+ if (state.channel_id)
6006
+ states.set(state.user_id, state);
6007
+ else
6008
+ states.delete(state.user_id);
6009
+ }
6010
+ #upsertRole(guildId, data) {
6011
+ if (!this.#cache.roles)
6012
+ return new Role(data);
6013
+ return this.#merge(this.guilds.roles(guildId), data.id, new Role(data));
6014
+ }
6015
+ #merge(manager, id, next) {
6016
+ const existing = manager.get(id);
6017
+ if (!existing) {
6018
+ manager.set(id, next);
6019
+ return next;
6020
+ }
6021
+ for (const [key, value] of Object.entries(next))
6022
+ if (value !== undefined)
6023
+ existing[key] = value;
6024
+ return existing;
6025
+ }
6026
+ createCollector(event, options = {}) {
6027
+ const collector = new Collector(options);
6028
+ let order = 0;
6029
+ const listener = (...args) => {
6030
+ const item = args[0];
6031
+ const id = item?.id;
6032
+ const key = options.key?.(item) ?? (typeof id === "string" ? id : String(order++));
6033
+ collector.handle(key, item).catch((error) => this.emit("error" /* Error */, error instanceof Error ? error : new Error(String(error))));
6034
+ };
6035
+ this.on(event, listener);
6036
+ collector.onDispose(() => this.off(event, listener));
6037
+ return collector;
6038
+ }
6039
+ get resourceContext() {
6040
+ return this.#resourceContext;
6041
+ }
6042
+ #memberPermissions(guildId, memberId, roleIds, channelId) {
6043
+ const guild = this.guilds.get(guildId);
6044
+ if (!guild)
6045
+ return null;
6046
+ let channel = channelId ? this.channels.get(channelId) : undefined;
6047
+ if (channelId) {
6048
+ if (channel?.isThread())
6049
+ channel = channel.parentId ? this.channels.get(channel.parentId) : undefined;
6050
+ if (!channel || channel.guildId !== guildId)
6051
+ return null;
6052
+ }
6053
+ return computePermissions({
6054
+ guildId,
6055
+ ownerId: guild.ownerId,
6056
+ memberId,
6057
+ memberRoleIds: [...roleIds],
6058
+ roles: this.guilds.roles(guildId).values(),
6059
+ overwrites: channel?.permissionOverwrites
6060
+ });
6061
+ }
6062
+ permissionsFor(memberId, guildOrChannelId) {
6063
+ let channel = this.channels.get(guildOrChannelId);
6064
+ if (channel?.isThread()) {
6065
+ channel = channel.parentId ? this.channels.get(channel.parentId) : undefined;
6066
+ if (!channel)
6067
+ return null;
6068
+ }
6069
+ const guildId = channel?.guildId ?? guildOrChannelId;
6070
+ const guild = this.guilds.get(guildId);
6071
+ const member = this.guilds.members(guildId).get(memberId);
6072
+ if (!guild || !member)
6073
+ return null;
6074
+ return computePermissions({
6075
+ guildId,
6076
+ ownerId: guild.ownerId,
6077
+ memberId,
6078
+ memberRoleIds: member.roleIds,
6079
+ roles: this.guilds.roles(guildId).values(),
6080
+ overwrites: channel?.permissionOverwrites
6081
+ });
6082
+ }
6083
+ fetchDefaultSoundboardSounds() {
6084
+ return this.rest.get(Routes.soundboardDefaultSounds());
6085
+ }
4493
6086
  async login(token) {
4494
6087
  if (this.state === "destroyed")
4495
6088
  throw new Error("Cannot login a destroyed client.");
@@ -4509,12 +6102,21 @@ class Client extends EventEmitter2 {
4509
6102
  this.#gateway.close();
4510
6103
  }
4511
6104
  postInteractionResponse(id, token, response) {
4512
- return this.rest.post(Routes.interactionCallback(id, token), response.toJSON());
6105
+ const json = response.toJSON();
6106
+ const upload = json.data ? toRequest(json.data) : undefined;
6107
+ if (upload && typeof upload === "object" && "files" in upload) {
6108
+ const { body, files } = upload;
6109
+ return this.rest.post(Routes.interactionCallback(id, token), {
6110
+ body: { ...json, data: body },
6111
+ files
6112
+ });
6113
+ }
6114
+ return this.rest.post(Routes.interactionCallback(id, token), json);
4513
6115
  }
4514
6116
  editInteractionReply(token, data) {
4515
6117
  if (!this.user)
4516
6118
  return Promise.reject(new Error("Client is unauthenticated."));
4517
- return this.rest.patch(Routes.interactionOriginalResponse(this.user.id, token), data);
6119
+ return this.rest.patch(Routes.interactionOriginalResponse(this.user.id, token), toRequest(data));
4518
6120
  }
4519
6121
  deleteInteractionReply(token) {
4520
6122
  if (!this.user)
@@ -4524,7 +6126,15 @@ class Client extends EventEmitter2 {
4524
6126
  followUpInteraction(token, data) {
4525
6127
  if (!this.user)
4526
6128
  return Promise.reject(new Error("Client is unauthenticated."));
4527
- return this.rest.post(`/webhooks/${this.user.id}/${token}`, data);
6129
+ return this.rest.post(`/webhooks/${this.user.id}/${token}`, toRequest(data));
6130
+ }
6131
+ interactionWebhookMessage(method, applicationId, token, messageId, data) {
6132
+ const path = messageId === "@original" ? Routes.interactionOriginalResponse(applicationId, token) : Routes.webhookMessage(applicationId, token, messageId);
6133
+ if (method === "GET")
6134
+ return this.rest.get(path);
6135
+ if (method === "PATCH")
6136
+ return this.rest.patch(path, data);
6137
+ return this.rest.delete(path);
4528
6138
  }
4529
6139
  fetchWebhook(id, token) {
4530
6140
  return this.rest.get(token ? `/webhooks/${id}/${token}` : `/webhooks/${id}`);
@@ -4583,7 +6193,8 @@ export {
4583
6193
  PermissionSet,
4584
6194
  Permissions,
4585
6195
  PermissionsBitField,
6196
+ computePermissions,
4586
6197
  resolveGatewayIntents
4587
6198
  };
4588
6199
 
4589
- //# debugId=B9E28396E97D857564756E2164756E21
6200
+ //# debugId=C58DF09843ED07E364756E2164756E21