lunibee 0.2.2 → 0.2.4

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 (70) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +225 -225
  3. package/dist/builders/attachment.d.ts +10 -2
  4. package/dist/builders/commands.d.ts +161 -101
  5. package/dist/builders/components.d.ts +54 -75
  6. package/dist/builders/embed.d.ts +68 -35
  7. package/dist/builders/index.d.ts +1 -1
  8. package/dist/builders/index.js +108 -133
  9. package/dist/builders/index.js.map +8 -8
  10. package/dist/collection/cache.d.ts +13 -6
  11. package/dist/collection/index.d.ts +90 -17
  12. package/dist/collection/index.js +442 -266
  13. package/dist/collection/index.js.map +4 -4
  14. package/dist/core/index.d.ts +9 -0
  15. package/dist/core/index.js +791 -436
  16. package/dist/core/index.js.map +47 -47
  17. package/dist/core/permissions.d.ts +9 -5
  18. package/dist/formatters/index.js +9 -5
  19. package/dist/formatters/index.js.map +3 -3
  20. package/dist/handlers/index.js +5 -10
  21. package/dist/handlers/index.js.map +3 -3
  22. package/dist/index.js +1010 -679
  23. package/dist/index.js.map +66 -65
  24. package/dist/managers/base.d.ts +26 -14
  25. package/dist/managers/emoji.d.ts +7 -1
  26. package/dist/managers/guild-resources.d.ts +11 -3
  27. package/dist/managers/guild.d.ts +13 -5
  28. package/dist/managers/index.d.ts +28 -14
  29. package/dist/managers/index.js +580 -340
  30. package/dist/managers/index.js.map +26 -26
  31. package/dist/managers/member.d.ts +5 -3
  32. package/dist/managers/message.d.ts +7 -3
  33. package/dist/managers/role.d.ts +13 -1
  34. package/dist/rest/error-codes.d.ts +48 -0
  35. package/dist/rest/errors.d.ts +14 -6
  36. package/dist/rest/index.d.ts +25 -12
  37. package/dist/rest/index.js +105 -18
  38. package/dist/rest/index.js.map +15 -14
  39. package/dist/rest/redis.d.ts +1 -1
  40. package/dist/rest/route.d.ts +8 -4
  41. package/dist/rest/routes.d.ts +102 -46
  42. package/dist/rest/transport.d.ts +10 -5
  43. package/dist/rest/webhook.d.ts +9 -5
  44. package/dist/sharding/bus.d.ts +34 -17
  45. package/dist/sharding/index.d.ts +34 -17
  46. package/dist/sharding/index.js +68 -36
  47. package/dist/sharding/index.js.map +17 -17
  48. package/dist/structures/base.d.ts +28 -10
  49. package/dist/structures/channels.d.ts +28 -14
  50. package/dist/structures/index.d.ts +6 -6
  51. package/dist/structures/index.js +81 -99
  52. package/dist/structures/index.js.map +19 -18
  53. package/dist/structures/interactions.d.ts +98 -50
  54. package/dist/structures/resources.d.ts +90 -46
  55. package/dist/types/gateway.d.ts +1 -1
  56. package/dist/types/index.d.ts +43 -18
  57. package/dist/types/index.js +20 -22
  58. package/dist/types/index.js.map +4 -4
  59. package/dist/utils/index.js.map +2 -2
  60. package/dist/voice/index.d.ts +12 -4
  61. package/dist/voice/index.js +17 -20
  62. package/dist/voice/index.js.map +3 -3
  63. package/dist/ws/decoder.d.ts +6 -2
  64. package/dist/ws/index.d.ts +25 -13
  65. package/dist/ws/index.js +63 -31
  66. package/dist/ws/index.js.map +14 -14
  67. package/dist/ws/protocol.d.ts +10 -2
  68. package/dist/ws/session.d.ts +14 -4
  69. package/dist/ws/state.d.ts +22 -11
  70. package/package.json +16 -15
package/dist/index.js CHANGED
@@ -114,60 +114,7 @@ var Permissions = {
114
114
  PinMessages: 1n << 51n,
115
115
  BypassSlowmode: 1n << 52n
116
116
  };
117
- var PermissionFlagsBits = {
118
- CreateInstantInvite: 1n << 0n,
119
- KickMembers: 1n << 1n,
120
- BanMembers: 1n << 2n,
121
- Administrator: 1n << 3n,
122
- ManageChannels: 1n << 4n,
123
- ManageGuild: 1n << 5n,
124
- AddReactions: 1n << 6n,
125
- ViewAuditLog: 1n << 7n,
126
- PrioritySpeaker: 1n << 8n,
127
- Stream: 1n << 9n,
128
- ViewChannel: 1n << 10n,
129
- SendMessages: 1n << 11n,
130
- SendTTSMessages: 1n << 12n,
131
- ManageMessages: 1n << 13n,
132
- EmbedLinks: 1n << 14n,
133
- AttachFiles: 1n << 15n,
134
- ReadMessageHistory: 1n << 16n,
135
- MentionEveryone: 1n << 17n,
136
- UseExternalEmojis: 1n << 18n,
137
- ViewGuildInsights: 1n << 19n,
138
- Connect: 1n << 20n,
139
- Speak: 1n << 21n,
140
- MuteMembers: 1n << 22n,
141
- DeafenMembers: 1n << 23n,
142
- MoveMembers: 1n << 24n,
143
- UseVAD: 1n << 25n,
144
- ChangeNickname: 1n << 26n,
145
- ManageNicknames: 1n << 27n,
146
- ManageRoles: 1n << 28n,
147
- ManageWebhooks: 1n << 29n,
148
- ManageGuildExpressions: 1n << 30n,
149
- UseApplicationCommands: 1n << 31n,
150
- RequestToSpeak: 1n << 32n,
151
- ManageEvents: 1n << 33n,
152
- ManageThreads: 1n << 34n,
153
- CreatePublicThreads: 1n << 35n,
154
- CreatePrivateThreads: 1n << 36n,
155
- UseExternalStickers: 1n << 37n,
156
- SendMessagesInThreads: 1n << 38n,
157
- UseEmbeddedActivities: 1n << 39n,
158
- ModerateMembers: 1n << 40n,
159
- ViewCreatorMonetizationAnalytics: 1n << 41n,
160
- UseSoundboard: 1n << 42n,
161
- CreateGuildExpressions: 1n << 43n,
162
- CreateEvents: 1n << 44n,
163
- UseExternalSounds: 1n << 45n,
164
- SendVoiceMessages: 1n << 46n,
165
- SetVoiceChannelStatus: 1n << 48n,
166
- SendPolls: 1n << 49n,
167
- UseExternalApps: 1n << 50n,
168
- PinMessages: 1n << 51n,
169
- BypassSlowmode: 1n << 52n
170
- };
117
+ var PermissionFlagsBits = Permissions;
171
118
 
172
119
  class PermissionSet {
173
120
  bitfield;
@@ -468,6 +415,9 @@ function computePermissions(context) {
468
415
  const member = overwrites.find((o) => o.type === 1 /* Member */ && o.id === context.memberId);
469
416
  if (member)
470
417
  base = base & ~bits(member.deny) | bits(member.allow);
418
+ const until = context.timedOutUntil instanceof Date ? context.timedOutUntil.getTime() : context.timedOutUntil ?? 0;
419
+ if (until > Date.now())
420
+ base &= Permission.viewChannel | Permission.readMessageHistory;
471
421
  return new PermissionSet(base);
472
422
  }
473
423
  // packages/core/src/events.ts
@@ -742,28 +692,26 @@ var IntentBits = {
742
692
  };
743
693
  var Intents = IntentBits;
744
694
  function resolveGatewayIntents(intents) {
745
- if (typeof intents === "number")
746
- return intents;
747
- if (intents && typeof intents === "object" && !Array.isArray(intents))
695
+ if (Array.isArray(intents))
696
+ return intents.reduce((acc, intent) => acc | resolveIntent(intent), 0);
697
+ if (typeof intents === "object")
748
698
  return intents.bitfield;
749
- if (Array.isArray(intents)) {
750
- return intents.reduce((acc, intent) => {
751
- return acc | resolveGatewayIntents(intent);
752
- }, 0);
753
- }
754
- if (typeof intents === "string") {
755
- if (intents in GatewayIntentBits)
756
- return GatewayIntentBits[intents];
757
- if (intents in IntentBits)
758
- return IntentBits[intents];
759
- const lower = intents.charAt(0).toLowerCase() + intents.slice(1);
760
- if (lower in IntentBits)
761
- return IntentBits[lower];
762
- const num = Number(intents);
763
- if (!Number.isNaN(num))
764
- return num;
765
- }
766
- return 0;
699
+ return resolveIntent(intents);
700
+ }
701
+ function resolveIntent(intent) {
702
+ if (typeof intent === "number")
703
+ return intent;
704
+ const bits = {
705
+ ...IntentBits,
706
+ ...GatewayIntentBits
707
+ };
708
+ const lower = intent.charAt(0).toLowerCase() + intent.slice(1);
709
+ if (Object.hasOwn(bits, intent))
710
+ return bits[intent];
711
+ if (Object.hasOwn(bits, lower))
712
+ return bits[lower];
713
+ const num = Number(intent);
714
+ return Number.isNaN(num) ? 0 : num;
767
715
  }
768
716
 
769
717
  class IntentsBitField {
@@ -830,6 +778,24 @@ var ChannelEnum = {
830
778
  GuildForum: 15,
831
779
  GuildMedia: 16
832
780
  };
781
+ var ComponentEnum = {
782
+ ActionRow: 1,
783
+ Button: 2,
784
+ StringSelect: 3,
785
+ TextInput: 4,
786
+ UserSelect: 5,
787
+ RoleSelect: 6,
788
+ MentionableSelect: 7,
789
+ ChannelSelect: 8,
790
+ Section: 9,
791
+ TextDisplay: 10,
792
+ Thumbnail: 11,
793
+ MediaGallery: 12,
794
+ File: 13,
795
+ Separator: 14,
796
+ ContentInventoryEntry: 16,
797
+ Container: 17
798
+ };
833
799
  var ButtonType = {
834
800
  Primary: 1,
835
801
  Secondary: 2,
@@ -904,64 +870,36 @@ var StickerType = StickerEnum;
904
870
  var StickerFormatType = StickerFormatEnum;
905
871
  // packages/collection/src/cache.ts
906
872
  class Cache {
907
- #entries = new Collection;
908
- #maxSize;
909
- #ttl;
910
- #timer;
873
+ #entries;
911
874
  constructor(options = {}) {
912
- this.#maxSize = options.maxSize ?? Infinity;
913
- this.#ttl = options.ttl ?? 0;
914
- if (!Number.isInteger(this.#maxSize) && this.#maxSize !== Infinity || this.#maxSize < 1)
875
+ const maxSize = options.maxSize ?? Infinity;
876
+ const ttl = options.ttl ?? 0;
877
+ if (!Number.isInteger(maxSize) && maxSize !== Infinity || maxSize < 1)
915
878
  throw new RangeError("Cache maxSize must be a positive integer.");
916
- if (!Number.isFinite(this.#ttl) || this.#ttl < 0)
879
+ if (!Number.isFinite(ttl) || ttl < 0)
917
880
  throw new RangeError("Cache ttl must be a non-negative finite number.");
918
- if (this.#ttl > 0) {
919
- const interval = options.sweepInterval ?? Math.min(this.#ttl, 60000);
881
+ if (ttl > 0) {
882
+ const interval = options.sweepInterval ?? Math.min(ttl, 60000);
920
883
  if (!Number.isFinite(interval) || interval < 1)
921
884
  throw new RangeError("Cache sweepInterval must be positive.");
922
- this.#timer = setInterval(() => this.sweep(), interval);
923
- this.#timer.unref?.();
924
885
  }
886
+ this.#entries = new Collection(null, {
887
+ ttl: ttl > 0 ? ttl : undefined,
888
+ maxSize: maxSize === Infinity ? undefined : maxSize,
889
+ slide: false
890
+ });
925
891
  }
926
892
  get size() {
927
- this.#sweepExpired();
928
893
  return this.#entries.size;
929
894
  }
930
895
  get(key) {
931
- const entry = this.#entries.get(key);
932
- if (!entry)
933
- return;
934
- if (entry.expiresAt > 0 && entry.expiresAt <= Date.now()) {
935
- this.#entries.delete(key);
936
- return;
937
- }
938
- this.#entries.delete(key);
939
- this.#entries.set(key, entry);
940
- return entry.value;
896
+ return this.#entries.get(key);
941
897
  }
942
898
  has(key) {
943
- const entry = this.#entries.get(key);
944
- if (!entry)
945
- return false;
946
- if (entry.expiresAt > 0 && entry.expiresAt <= Date.now()) {
947
- this.#entries.delete(key);
948
- return false;
949
- }
950
- return true;
899
+ return this.#entries.has(key);
951
900
  }
952
901
  set(key, value) {
953
- const expiresAt = this.#ttl > 0 ? Date.now() + this.#ttl : 0;
954
- this.#entries.delete(key);
955
- this.#entries.set(key, { value, expiresAt });
956
- if (this.#maxSize !== Infinity) {
957
- while (this.#entries.size > this.#maxSize) {
958
- const oldest = this.#entries.firstKey();
959
- if (oldest !== undefined)
960
- this.#entries.delete(oldest);
961
- else
962
- break;
963
- }
964
- }
902
+ this.#entries.set(key, value);
965
903
  return this;
966
904
  }
967
905
  delete(key) {
@@ -971,95 +909,52 @@ class Cache {
971
909
  this.#entries.clear();
972
910
  }
973
911
  invalidate(predicate) {
974
- return this.#entries.sweep((entry, key) => predicate(entry.value, key));
912
+ return this.#entries.sweep(predicate);
975
913
  }
976
914
  sweep() {
977
- return this.#entries.sweep((entry) => this.#expired(entry));
978
- }
979
- dispose() {
980
- if (this.#timer)
981
- clearInterval(this.#timer);
982
- this.#timer = undefined;
915
+ return this.#entries.purge();
983
916
  }
917
+ dispose() {}
984
918
  values() {
985
- this.#sweepExpired();
986
- return this.#entries.map((entry) => entry.value);
919
+ return [...this.#entries.values()];
987
920
  }
988
921
  entries() {
989
- this.#sweepExpired();
990
- return this.#entries.map((entry, key) => [key, entry.value]);
991
- }
992
- #expired(entry) {
993
- return entry.expiresAt > 0 && entry.expiresAt <= Date.now();
994
- }
995
- #sweepExpired() {
996
- if (this.#ttl > 0)
997
- this.sweep();
922
+ return [...this.#entries.entries()];
998
923
  }
999
924
  }
1000
925
 
1001
926
  // packages/collection/src/index.ts
1002
- class RecencyList {
1003
- #nodes = new Map;
1004
- #oldest;
1005
- #newest;
1006
- get size() {
1007
- return this.#nodes.size;
1008
- }
1009
- oldest() {
1010
- return this.#oldest?.key;
1011
- }
1012
- touch(key) {
1013
- const node = this.#nodes.get(key);
1014
- if (node)
1015
- return this.#moveNewest(node);
1016
- const created = { key, older: this.#newest };
1017
- if (this.#newest)
1018
- this.#newest.newer = created;
1019
- else
1020
- this.#oldest = created;
1021
- this.#newest = created;
1022
- this.#nodes.set(key, created);
1023
- }
1024
- promote(key) {
1025
- const node = this.#nodes.get(key);
1026
- if (node)
1027
- this.#moveNewest(node);
1028
- }
1029
- delete(key) {
1030
- const node = this.#nodes.get(key);
1031
- if (!node)
1032
- return false;
1033
- this.#unlink(node);
1034
- this.#nodes.delete(key);
1035
- return true;
1036
- }
1037
- clear() {
1038
- this.#nodes.clear();
1039
- this.#oldest = this.#newest = undefined;
1040
- }
1041
- #unlink(node) {
1042
- if (node.older)
1043
- node.older.newer = node.newer;
1044
- else
1045
- this.#oldest = node.newer;
1046
- if (node.newer)
1047
- node.newer.older = node.older;
1048
- else
1049
- this.#newest = node.older;
1050
- node.older = node.newer = undefined;
1051
- }
1052
- #moveNewest(node) {
1053
- if (node === this.#newest)
1054
- return;
1055
- this.#unlink(node);
1056
- node.older = this.#newest;
1057
- if (this.#newest)
1058
- this.#newest.newer = node;
1059
- else
1060
- this.#oldest = node;
1061
- this.#newest = node;
927
+ function newPolicy(options = {}) {
928
+ return {
929
+ ttl: options.ttl,
930
+ maxSize: options.maxSize,
931
+ slide: options.slide ?? true,
932
+ onEvict: options.onEvict,
933
+ expired: 0,
934
+ evicted: 0,
935
+ entries: new Map,
936
+ oldest: undefined,
937
+ newest: undefined,
938
+ lruSize: 0,
939
+ heap: [],
940
+ armedFor: Infinity
941
+ };
942
+ }
943
+ function peekOf(collection, key) {
944
+ return collection instanceof Map ? Map.prototype.get.call(collection, key) : collection.get(key);
945
+ }
946
+ var mapGet = Map.prototype.get;
947
+ var mapHas = Map.prototype.has;
948
+ function sample(items, amount) {
949
+ if (!Number.isInteger(amount) || amount < 0)
950
+ throw new RangeError("amount must be a non-negative integer.");
951
+ const count = Math.min(amount, items.length);
952
+ for (let i = 0;i < count; i++) {
953
+ const j = i + Math.floor(Math.random() * (items.length - i));
954
+ [items[i], items[j]] = [items[j], items[i]];
1062
955
  }
956
+ items.length = count;
957
+ return items;
1063
958
  }
1064
959
  function assertTTL(ttl) {
1065
960
  if (ttl !== undefined && (!Number.isFinite(ttl) || ttl <= 0))
@@ -1067,81 +962,90 @@ function assertTTL(ttl) {
1067
962
  }
1068
963
 
1069
964
  class Collection extends Map {
1070
- #ttl;
1071
- #maxSize;
1072
- #onEvict;
1073
- #expiry = new Map;
1074
- #lru = new RecencyList;
1075
- #stats = {
1076
- hits: 0,
1077
- misses: 0,
1078
- expired: 0,
1079
- evicted: 0
1080
- };
1081
- #heap = [];
1082
- #timer;
1083
- #armedFor = Infinity;
965
+ #policy;
966
+ #hits = 0;
967
+ #misses = 0;
1084
968
  constructor(entries, options = {}) {
1085
969
  super();
1086
970
  assertTTL(options.ttl);
1087
971
  if (options.maxSize !== undefined && (!Number.isInteger(options.maxSize) || options.maxSize <= 0))
1088
972
  throw new RangeError("maxSize must be a positive integer.");
1089
- this.#ttl = options.ttl;
1090
- this.#maxSize = options.maxSize;
1091
- this.#onEvict = options.onEvict;
973
+ if (options.ttl !== undefined || options.maxSize !== undefined || options.slide !== undefined || options.onEvict !== undefined)
974
+ this.#policy = newPolicy(options);
1092
975
  if (entries)
1093
976
  for (const [key, value] of entries)
1094
977
  this.set(key, value);
1095
978
  }
1096
979
  set(key, value, ttl) {
980
+ if (ttl === undefined && this.#policy === undefined)
981
+ return super.set(key, value);
1097
982
  assertTTL(ttl);
1098
- const window = ttl ?? this.#ttl;
1099
- if (this.#maxSize !== undefined) {
1100
- this.#lru.touch(key);
1101
- }
1102
- super.set(key, value);
983
+ const window = ttl ?? this.#policy?.ttl;
1103
984
  if (window !== undefined)
1104
- this.#schedule(key, window);
1105
- else if (this.#expiry.size > 0)
1106
- this.#expiry.delete(key);
985
+ this.#policy ??= newPolicy();
986
+ if (!this.#policy)
987
+ return super.set(key, value);
988
+ const before = super.size;
989
+ super.set(key, value);
990
+ this.#track(key, value, window, super.size !== before);
1107
991
  this.#enforceCap();
1108
992
  return this;
1109
993
  }
1110
994
  setWithoutTTL(key, value) {
1111
- if (this.#expiry.size > 0)
1112
- this.#expiry.delete(key);
1113
- if (this.#lru.size > 0)
1114
- this.#lru.delete(key);
995
+ if (this.#policy)
996
+ this.#forget(key);
1115
997
  super.set(key, value);
1116
998
  return this;
1117
999
  }
1118
1000
  get(key) {
1119
- if (this.#expireIfDue(key)) {
1120
- this.#stats.misses++;
1001
+ const policy = this.#policy;
1002
+ const entry = policy?.entries.get(key);
1003
+ if (entry === undefined) {
1004
+ const value = mapGet.call(this, key);
1005
+ if (value !== undefined || mapHas.call(this, key)) {
1006
+ this.#hits++;
1007
+ return value;
1008
+ }
1009
+ this.#misses++;
1121
1010
  return;
1122
1011
  }
1123
- const value = super.get(key);
1124
- if (value === undefined && !super.has(key)) {
1125
- this.#stats.misses++;
1012
+ const timed = entry.window !== 0;
1013
+ const now = timed ? Date.now() : 0;
1014
+ if (timed && entry.deadline <= now) {
1015
+ this.#expire(entry);
1016
+ this.#misses++;
1126
1017
  return;
1127
1018
  }
1128
- this.#stats.hits++;
1129
- const expiry = this.#expiry.get(key);
1130
- if (expiry)
1131
- expiry.deadline = Date.now() + expiry.window;
1132
- this.#lru.promote(key);
1133
- return value;
1019
+ this.#hits++;
1020
+ if (timed && policy.slide)
1021
+ entry.deadline = now + entry.window;
1022
+ if (entry.inLru)
1023
+ this.#promote(policy, entry);
1024
+ return entry.value;
1025
+ }
1026
+ ensure(key, factory, ttl) {
1027
+ const existing = this.get(key);
1028
+ if (existing !== undefined || super.has(key))
1029
+ return existing;
1030
+ const created = factory(key, this);
1031
+ this.set(key, created, ttl);
1032
+ return created;
1134
1033
  }
1135
1034
  peek(key) {
1136
1035
  if (!this.#expireIfDue(key) && super.has(key)) {
1137
- this.#stats.hits++;
1036
+ this.#hits++;
1138
1037
  return super.get(key);
1139
1038
  }
1140
- this.#stats.misses++;
1039
+ this.#misses++;
1141
1040
  return;
1142
1041
  }
1143
1042
  get stats() {
1144
- return { ...this.#stats };
1043
+ return {
1044
+ hits: this.#hits,
1045
+ misses: this.#misses,
1046
+ expired: this.#policy?.expired ?? 0,
1047
+ evicted: this.#policy?.evicted ?? 0
1048
+ };
1145
1049
  }
1146
1050
  has(key) {
1147
1051
  return !this.#expireIfDue(key) && super.has(key);
@@ -1149,19 +1053,23 @@ class Collection extends Map {
1149
1053
  delete(key) {
1150
1054
  if (this.#expireIfDue(key))
1151
1055
  return false;
1152
- this.#expiry.delete(key);
1153
- this.#lru.delete(key);
1056
+ if (this.#policy)
1057
+ this.#forget(key);
1154
1058
  return super.delete(key);
1155
1059
  }
1156
1060
  clear() {
1157
1061
  super.clear();
1158
- this.#expiry.clear();
1159
- this.#lru.clear();
1160
- this.#heap.length = 0;
1161
- if (this.#timer)
1162
- clearTimeout(this.#timer);
1163
- this.#timer = undefined;
1164
- this.#armedFor = Infinity;
1062
+ const policy = this.#policy;
1063
+ if (!policy)
1064
+ return;
1065
+ policy.entries.clear();
1066
+ policy.oldest = policy.newest = undefined;
1067
+ policy.lruSize = 0;
1068
+ policy.heap.length = 0;
1069
+ if (policy.timer)
1070
+ clearTimeout(policy.timer);
1071
+ policy.timer = undefined;
1072
+ policy.armedFor = Infinity;
1165
1073
  }
1166
1074
  get size() {
1167
1075
  this.purge();
@@ -1189,11 +1097,11 @@ class Collection extends Map {
1189
1097
  ttlRemaining(key) {
1190
1098
  if (this.#expireIfDue(key))
1191
1099
  return;
1192
- const expiry = this.#expiry.get(key);
1193
- return expiry && Math.max(0, expiry.deadline - Date.now());
1100
+ const entry = this.#policy?.entries.get(key);
1101
+ return entry && entry.window !== 0 ? Math.max(0, entry.deadline - Date.now()) : undefined;
1194
1102
  }
1195
1103
  purge() {
1196
- if (this.#expiry.size === 0)
1104
+ if (!this.#policy || this.#policy.heap.length === 0)
1197
1105
  return 0;
1198
1106
  const now = Date.now();
1199
1107
  let removed = 0;
@@ -1204,133 +1112,255 @@ class Collection extends Map {
1204
1112
  this.#remove(due.key);
1205
1113
  removed++;
1206
1114
  }
1207
- this.#stats.expired += removed;
1115
+ this.#policy.expired += removed;
1208
1116
  this.#rearm();
1209
1117
  for (const [key, value] of dropped)
1210
1118
  this.#notify(key, value, "expired");
1211
1119
  return removed;
1212
1120
  }
1213
1121
  #expireIfDue(key) {
1214
- const expiry = this.#expiry.get(key);
1215
- if (!expiry || expiry.deadline > Date.now())
1122
+ const entry = this.#policy?.entries.get(key);
1123
+ if (!entry || entry.window === 0 || entry.deadline > Date.now())
1216
1124
  return false;
1217
- const value = super.get(key);
1218
- this.#remove(key);
1219
- this.#stats.expired++;
1220
- this.#notify(key, value, "expired");
1125
+ this.#expire(entry);
1221
1126
  return true;
1222
1127
  }
1128
+ #expire(entry) {
1129
+ const value = super.get(entry.key);
1130
+ this.#remove(entry.key);
1131
+ this.#policy.expired++;
1132
+ this.#notify(entry.key, value, "expired");
1133
+ }
1223
1134
  #remove(key) {
1224
- this.#expiry.delete(key);
1225
- this.#lru.delete(key);
1135
+ this.#forget(key);
1226
1136
  super.delete(key);
1227
1137
  }
1138
+ #forget(key) {
1139
+ const policy = this.#policy;
1140
+ const entry = policy.entries.get(key);
1141
+ if (!entry)
1142
+ return;
1143
+ if (entry.inLru)
1144
+ this.#unlink(policy, entry);
1145
+ policy.entries.delete(key);
1146
+ }
1147
+ #track(key, value, window, isNew) {
1148
+ const policy = this.#policy;
1149
+ const lru = policy.maxSize !== undefined;
1150
+ let entry = isNew ? undefined : policy.entries.get(key);
1151
+ if (entry)
1152
+ entry.value = value;
1153
+ if (window === undefined) {
1154
+ if (entry && entry.window !== 0) {
1155
+ if (lru)
1156
+ entry = this.#replace(policy, entry, 0, 0);
1157
+ else {
1158
+ this.#forget(key);
1159
+ return;
1160
+ }
1161
+ }
1162
+ if (!entry && lru) {
1163
+ entry = this.#create(key, value, 0, 0);
1164
+ policy.entries.set(key, entry);
1165
+ }
1166
+ if (entry)
1167
+ this.#promote(policy, entry);
1168
+ return;
1169
+ }
1170
+ const deadline = Date.now() + window;
1171
+ if (entry && entry.window !== 0) {
1172
+ entry.deadline = deadline;
1173
+ entry.window = window;
1174
+ if (deadline < entry.filed)
1175
+ entry = this.#replace(policy, entry, window, deadline);
1176
+ else {
1177
+ if (entry.inLru)
1178
+ this.#promote(policy, entry);
1179
+ return;
1180
+ }
1181
+ } else if (entry) {
1182
+ entry.window = window;
1183
+ entry.deadline = entry.filed = deadline;
1184
+ } else {
1185
+ entry = this.#create(key, value, window, deadline);
1186
+ policy.entries.set(key, entry);
1187
+ }
1188
+ if (lru)
1189
+ this.#promote(policy, entry);
1190
+ this.#heapPush(entry);
1191
+ if (policy.heap.length > 2 * policy.entries.size + 8)
1192
+ this.#compact();
1193
+ if (policy.timer === undefined || deadline < policy.armedFor)
1194
+ this.#rearm();
1195
+ }
1196
+ #create(key, value, window, deadline) {
1197
+ return {
1198
+ key,
1199
+ value,
1200
+ older: undefined,
1201
+ newer: undefined,
1202
+ inLru: false,
1203
+ window,
1204
+ deadline,
1205
+ filed: deadline
1206
+ };
1207
+ }
1208
+ #replace(policy, old, window, deadline) {
1209
+ const entry = {
1210
+ ...old,
1211
+ window,
1212
+ deadline,
1213
+ filed: deadline
1214
+ };
1215
+ if (old.inLru) {
1216
+ if (old.older)
1217
+ old.older.newer = entry;
1218
+ else
1219
+ policy.oldest = entry;
1220
+ if (old.newer)
1221
+ old.newer.older = entry;
1222
+ else
1223
+ policy.newest = entry;
1224
+ }
1225
+ policy.entries.set(old.key, entry);
1226
+ return entry;
1227
+ }
1228
+ #promote(policy, entry) {
1229
+ if (entry === policy.newest)
1230
+ return;
1231
+ if (entry.inLru)
1232
+ this.#unlink(policy, entry, true);
1233
+ else {
1234
+ entry.inLru = true;
1235
+ policy.lruSize++;
1236
+ }
1237
+ entry.older = policy.newest;
1238
+ entry.newer = undefined;
1239
+ if (policy.newest)
1240
+ policy.newest.newer = entry;
1241
+ else
1242
+ policy.oldest = entry;
1243
+ policy.newest = entry;
1244
+ }
1245
+ #unlink(policy, entry, keepCount = false) {
1246
+ if (entry.older)
1247
+ entry.older.newer = entry.newer;
1248
+ else
1249
+ policy.oldest = entry.newer;
1250
+ if (entry.newer)
1251
+ entry.newer.older = entry.older;
1252
+ else
1253
+ policy.newest = entry.older;
1254
+ entry.older = entry.newer = undefined;
1255
+ if (!keepCount) {
1256
+ entry.inLru = false;
1257
+ policy.lruSize--;
1258
+ }
1259
+ }
1260
+ #derived() {
1261
+ const Species = this.constructor[Symbol.species] ?? Collection;
1262
+ return new Species;
1263
+ }
1228
1264
  #notify(key, value, reason) {
1229
- if (!this.#onEvict)
1265
+ const onEvict = this.#policy?.onEvict;
1266
+ if (!onEvict)
1230
1267
  return;
1231
1268
  try {
1232
- this.#onEvict(key, value, reason);
1269
+ onEvict(key, value, reason);
1233
1270
  } catch {}
1234
1271
  }
1235
1272
  #enforceCap() {
1236
- if (this.#maxSize === undefined)
1273
+ const policy = this.#policy;
1274
+ const max = policy.maxSize;
1275
+ if (max === undefined)
1237
1276
  return;
1238
- while (this.#lru.size > this.#maxSize) {
1239
- const oldest = this.#lru.oldest();
1240
- const value = super.get(oldest);
1241
- this.#remove(oldest);
1242
- this.#stats.evicted++;
1243
- this.#notify(oldest, value, "evicted");
1277
+ if (policy.lruSize > max && policy.heap.length > 0 && policy.heap[0].filed <= Date.now())
1278
+ this.purge();
1279
+ while (policy.lruSize > max) {
1280
+ const oldest = policy.oldest;
1281
+ const value = policy.onEvict ? super.get(oldest.key) : undefined;
1282
+ this.#unlink(policy, oldest);
1283
+ policy.entries.delete(oldest.key);
1284
+ super.delete(oldest.key);
1285
+ policy.evicted++;
1286
+ this.#notify(oldest.key, value, "evicted");
1244
1287
  }
1245
1288
  }
1246
- #schedule(key, window) {
1247
- const deadline = Date.now() + window;
1248
- const expiry = this.#expiry.get(key);
1249
- if (expiry) {
1250
- expiry.deadline = deadline;
1251
- expiry.window = window;
1252
- if (deadline >= expiry.filed)
1253
- return;
1254
- expiry.filed = deadline;
1255
- } else
1256
- this.#expiry.set(key, { deadline, window, filed: deadline });
1257
- this.#heapPush({ key, deadline });
1258
- if (this.#heap.length > 2 * this.#expiry.size + 8)
1259
- this.#compact();
1260
- this.#rearm();
1261
- }
1262
1289
  #nextDeadline() {
1290
+ const policy = this.#policy;
1263
1291
  for (;; ) {
1264
- const top = this.#heap[0];
1292
+ const top = policy.heap[0];
1265
1293
  if (top === undefined)
1266
1294
  return Infinity;
1267
- const expiry = this.#expiry.get(top.key);
1268
- if (!expiry || expiry.filed !== top.deadline) {
1295
+ if (policy.entries.get(top.key) !== top) {
1269
1296
  this.#heapPop();
1270
1297
  continue;
1271
1298
  }
1272
- if (expiry.deadline === top.deadline)
1273
- return top.deadline;
1299
+ if (top.deadline === top.filed)
1300
+ return top.filed;
1274
1301
  this.#heapPop();
1275
- expiry.filed = expiry.deadline;
1276
- this.#heapPush({ key: top.key, deadline: expiry.deadline });
1302
+ top.filed = top.deadline;
1303
+ this.#heapPush(top);
1277
1304
  }
1278
1305
  }
1279
1306
  #compact() {
1280
- const live = this.#heap.filter((record) => this.#expiry.get(record.key)?.filed === record.deadline);
1281
- this.#heap.length = 0;
1282
- for (const record of live)
1283
- this.#heapPush(record);
1307
+ const policy = this.#policy;
1308
+ const live = policy.heap.filter((entry) => policy.entries.get(entry.key) === entry);
1309
+ policy.heap.length = 0;
1310
+ for (const entry of live)
1311
+ this.#heapPush(entry);
1284
1312
  }
1285
1313
  #rearm() {
1314
+ const p = this.#policy;
1286
1315
  const deadline = this.#nextDeadline();
1287
- if (this.#timer !== undefined && deadline >= this.#armedFor)
1316
+ if (p.timer !== undefined && deadline >= p.armedFor)
1288
1317
  return;
1289
- if (this.#timer)
1290
- clearTimeout(this.#timer);
1291
- this.#timer = undefined;
1292
- this.#armedFor = deadline;
1318
+ if (p.timer)
1319
+ clearTimeout(p.timer);
1320
+ p.timer = undefined;
1321
+ p.armedFor = deadline;
1293
1322
  if (deadline === Infinity)
1294
1323
  return;
1295
- this.#timer = setTimeout(() => {
1296
- this.#timer = undefined;
1297
- this.#armedFor = Infinity;
1324
+ p.timer = setTimeout(() => {
1325
+ p.timer = undefined;
1326
+ p.armedFor = Infinity;
1298
1327
  this.purge();
1299
1328
  }, Math.max(0, deadline - Date.now()));
1300
- this.#timer.unref?.();
1329
+ p.timer.unref?.();
1301
1330
  }
1302
- #heapPush(record) {
1303
- const heap = this.#heap;
1304
- heap.push(record);
1305
- let i = heap.length - 1;
1331
+ #heapPush(entry) {
1332
+ const heap = this.#policy.heap;
1333
+ let i = heap.length;
1334
+ heap.push(entry);
1306
1335
  while (i > 0) {
1307
1336
  const parent = i - 1 >> 1;
1308
- if (heap[parent].deadline <= heap[i].deadline)
1337
+ const above = heap[parent];
1338
+ if (above.filed <= entry.filed)
1309
1339
  break;
1310
- [heap[parent], heap[i]] = [heap[i], heap[parent]];
1340
+ heap[i] = above;
1311
1341
  i = parent;
1312
1342
  }
1343
+ heap[i] = entry;
1313
1344
  }
1314
1345
  #heapPop() {
1315
- const heap = this.#heap;
1346
+ const heap = this.#policy.heap;
1316
1347
  const top = heap[0];
1317
1348
  const last = heap.pop();
1318
1349
  if (top === undefined || heap.length === 0)
1319
1350
  return top;
1320
- heap[0] = last;
1321
- for (let i = 0;; ) {
1322
- const left = 2 * i + 1;
1323
- const right = left + 1;
1324
- let smallest = i;
1325
- if (left < heap.length && heap[left].deadline < heap[smallest].deadline)
1326
- smallest = left;
1327
- if (right < heap.length && heap[right].deadline < heap[smallest].deadline)
1328
- smallest = right;
1329
- if (smallest === i)
1351
+ let i = 0;
1352
+ for (;; ) {
1353
+ let child = 2 * i + 1;
1354
+ if (child >= heap.length)
1330
1355
  break;
1331
- [heap[smallest], heap[i]] = [heap[i], heap[smallest]];
1332
- i = smallest;
1356
+ if (child + 1 < heap.length && heap[child + 1].filed < heap[child].filed)
1357
+ child++;
1358
+ if (heap[child].filed >= last.filed)
1359
+ break;
1360
+ heap[i] = heap[child];
1361
+ i = child;
1333
1362
  }
1363
+ heap[i] = last;
1334
1364
  return top;
1335
1365
  }
1336
1366
  first() {
@@ -1362,8 +1392,26 @@ class Collection extends Map {
1362
1392
  }
1363
1393
  return;
1364
1394
  }
1395
+ findLast(predicate) {
1396
+ const entries = [...this];
1397
+ for (let i = entries.length - 1;i >= 0; i--) {
1398
+ const [key, value] = entries[i];
1399
+ if (predicate(value, key, this))
1400
+ return value;
1401
+ }
1402
+ return;
1403
+ }
1404
+ findLastKey(predicate) {
1405
+ const entries = [...this];
1406
+ for (let i = entries.length - 1;i >= 0; i--) {
1407
+ const [key, value] = entries[i];
1408
+ if (predicate(value, key, this))
1409
+ return key;
1410
+ }
1411
+ return;
1412
+ }
1365
1413
  filter(predicate) {
1366
- const result = new Collection;
1414
+ const result = this.#derived();
1367
1415
  for (const [key, value] of this) {
1368
1416
  if (predicate(value, key, this))
1369
1417
  result.set(key, value);
@@ -1407,7 +1455,7 @@ class Collection extends Map {
1407
1455
  return [...this.entries()];
1408
1456
  }
1409
1457
  clone() {
1410
- const copy = new Collection;
1458
+ const copy = this.#derived();
1411
1459
  for (const [key, value] of this)
1412
1460
  copy.set(key, value);
1413
1461
  return copy;
@@ -1462,7 +1510,7 @@ class Collection extends Map {
1462
1510
  return result;
1463
1511
  }
1464
1512
  intersection(other) {
1465
- const result = new Collection;
1513
+ const result = this.#derived();
1466
1514
  for (const [key, value] of this) {
1467
1515
  if (other.has(key))
1468
1516
  result.set(key, value);
@@ -1470,7 +1518,7 @@ class Collection extends Map {
1470
1518
  return result;
1471
1519
  }
1472
1520
  difference(other) {
1473
- const result = new Collection;
1521
+ const result = this.#derived();
1474
1522
  for (const [key, value] of this) {
1475
1523
  if (!other.has(key))
1476
1524
  result.set(key, value);
@@ -1478,8 +1526,8 @@ class Collection extends Map {
1478
1526
  return result;
1479
1527
  }
1480
1528
  partition(predicate) {
1481
- const pass = new Collection;
1482
- const fail = new Collection;
1529
+ const pass = this.#derived();
1530
+ const fail = this.#derived();
1483
1531
  for (const [key, value] of this) {
1484
1532
  if (predicate(value, key, this))
1485
1533
  pass.set(key, value);
@@ -1488,6 +1536,81 @@ class Collection extends Map {
1488
1536
  }
1489
1537
  return [pass, fail];
1490
1538
  }
1539
+ symmetricDifference(other) {
1540
+ const result = this.#derived();
1541
+ for (const [key, value] of this)
1542
+ if (!other.has(key))
1543
+ result.set(key, value);
1544
+ for (const [key, value] of other)
1545
+ if (!this.has(key))
1546
+ result.set(key, value);
1547
+ return result;
1548
+ }
1549
+ concat(...collections) {
1550
+ const result = this.clone();
1551
+ for (const collection of collections)
1552
+ for (const [key, value] of collection)
1553
+ result.set(key, value);
1554
+ return result;
1555
+ }
1556
+ merge(other, whenInSelf, whenInOther, whenInBoth) {
1557
+ const result = this.#derived();
1558
+ const decide = (key, kept) => {
1559
+ if (kept.keep)
1560
+ result.set(key, kept.value);
1561
+ };
1562
+ for (const [key, value] of this) {
1563
+ decide(key, other.has(key) ? whenInBoth(value, peekOf(other, key), key) : whenInSelf(value, key));
1564
+ }
1565
+ for (const [key, value] of other)
1566
+ if (!this.has(key))
1567
+ decide(key, whenInOther(value, key));
1568
+ return result;
1569
+ }
1570
+ equals(other) {
1571
+ if (!other)
1572
+ return false;
1573
+ if (other === this)
1574
+ return true;
1575
+ if (this.size !== other.size)
1576
+ return false;
1577
+ for (const [key, value] of this) {
1578
+ if (!other.has(key))
1579
+ return false;
1580
+ if (value !== peekOf(other, key))
1581
+ return false;
1582
+ }
1583
+ return true;
1584
+ }
1585
+ mapValues(transform) {
1586
+ const result = this.#derived();
1587
+ for (const [key, value] of this)
1588
+ result.set(key, transform(value, key, this));
1589
+ return result;
1590
+ }
1591
+ toReversed() {
1592
+ const result = this.#derived();
1593
+ const entries = [...this];
1594
+ for (let i = entries.length - 1;i >= 0; i--)
1595
+ result.set(entries[i][0], entries[i][1]);
1596
+ return result;
1597
+ }
1598
+ toSorted(comparator) {
1599
+ return this.sorted(comparator);
1600
+ }
1601
+ static groupBy(items, keySelector) {
1602
+ const groups = new Collection;
1603
+ let index = 0;
1604
+ for (const item of items)
1605
+ groups.ensure(keySelector(item, index++), () => []).push(item);
1606
+ return groups;
1607
+ }
1608
+ static combineEntries(entries, combine) {
1609
+ const result = new Collection;
1610
+ for (const [key, value] of entries)
1611
+ result.set(key, result.has(key) ? combine(result.get(key), value, key) : value);
1612
+ return result;
1613
+ }
1491
1614
  tap(fn) {
1492
1615
  fn(this);
1493
1616
  return this;
@@ -1506,6 +1629,13 @@ class Collection extends Map {
1506
1629
  acc = fn(acc, value, key, this);
1507
1630
  return acc;
1508
1631
  }
1632
+ reduceRight(fn, initialValue) {
1633
+ const entries = [...this];
1634
+ let acc = initialValue;
1635
+ for (let i = entries.length - 1;i >= 0; i--)
1636
+ acc = fn(acc, entries[i][1], entries[i][0], this);
1637
+ return acc;
1638
+ }
1509
1639
  sorted(comparator) {
1510
1640
  const decorated = [...this.entries()].map((entry, index) => ({
1511
1641
  entry,
@@ -1516,22 +1646,34 @@ class Collection extends Map {
1516
1646
  const comparison = comparator(x.entry[1], y.entry[1], x.entry[0], y.entry[0]);
1517
1647
  return comparison !== 0 ? comparison : x.index - y.index;
1518
1648
  });
1519
- const result = new Collection;
1649
+ const result = this.#derived();
1520
1650
  for (const { entry } of decorated)
1521
1651
  result.set(entry[0], entry[1]);
1522
1652
  return result;
1523
1653
  }
1524
- random() {
1525
- const arr = [...this.values()];
1526
- if (!arr.length)
1654
+ random(amount) {
1655
+ if (amount !== undefined)
1656
+ return sample([...this.values()], amount);
1657
+ const size = this.size;
1658
+ if (size === 0)
1527
1659
  return;
1528
- return arr[Math.floor(Math.random() * arr.length)];
1660
+ let index = Math.floor(Math.random() * size);
1661
+ for (const value of this.values())
1662
+ if (index-- === 0)
1663
+ return value;
1664
+ return;
1529
1665
  }
1530
- randomKey() {
1531
- const arr = [...this.keys()];
1532
- if (!arr.length)
1666
+ randomKey(amount) {
1667
+ if (amount !== undefined)
1668
+ return sample([...this.keys()], amount);
1669
+ const size = this.size;
1670
+ if (size === 0)
1533
1671
  return;
1534
- return arr[Math.floor(Math.random() * arr.length)];
1672
+ let index = Math.floor(Math.random() * size);
1673
+ for (const key of this.keys())
1674
+ if (index-- === 0)
1675
+ return key;
1676
+ return;
1535
1677
  }
1536
1678
  at(index) {
1537
1679
  const arr = [...this.values()];
@@ -1549,6 +1691,11 @@ class Collection extends Map {
1549
1691
  }
1550
1692
 
1551
1693
  // packages/managers/src/base.ts
1694
+ function splitReason(options) {
1695
+ const { reason, ...payload } = options;
1696
+ return [payload, reason];
1697
+ }
1698
+
1552
1699
  class Manager {
1553
1700
  cache = new Collection;
1554
1701
  get(id) {
@@ -1650,12 +1797,15 @@ class ResourceManager extends Manager {
1650
1797
  // packages/rest/package.json
1651
1798
  var package_default = {
1652
1799
  name: "@lunibee/rest",
1653
- version: "0.2.2",
1800
+ version: "0.2.4",
1654
1801
  type: "module",
1655
1802
  module: "./src/index.ts",
1656
1803
  types: "./src/index.ts",
1657
1804
  exports: {
1658
1805
  ".": "./src/index.ts"
1806
+ },
1807
+ dependencies: {
1808
+ "@lunibee/types": "workspace:*"
1659
1809
  }
1660
1810
  };
1661
1811
 
@@ -1728,8 +1878,12 @@ function kindFromStatus(status) {
1728
1878
  return "client";
1729
1879
  }
1730
1880
  function redactPath(path) {
1731
- return path.replace(/^(\/webhooks\/[^/?]+\/)[^/?]+/, "$1:token").replace(/^(\/interactions\/[^/?]+\/)[^/?]+/, "$1:token");
1881
+ return path.replace(/^(\/webhooks\/[^/?]+\/)[^/?]+/i, "$1:token").replace(/^(\/interactions\/[^/?]+\/)[^/?]+/i, "$1:token");
1732
1882
  }
1883
+ var HINTS = {
1884
+ 50001: "The bot cannot see this resource: check that it is in the guild and has View Channel there.",
1885
+ 50013: "The bot lacks a permission for this action, or the target role or member is at or above the bot's highest role."
1886
+ };
1733
1887
 
1734
1888
  class RESTError extends Error {
1735
1889
  kind;
@@ -1738,12 +1892,14 @@ class RESTError extends Error {
1738
1892
  errors;
1739
1893
  method;
1740
1894
  path;
1895
+ hint;
1741
1896
  constructor(message, status, code, errors, options = {}) {
1742
1897
  super(message, options.cause === undefined ? undefined : { cause: options.cause });
1743
1898
  this.name = "RESTError";
1744
1899
  this.status = status;
1745
1900
  this.kind = options.kind ?? kindFromStatus(status);
1746
1901
  this.code = code;
1902
+ this.hint = code === undefined ? undefined : HINTS[code];
1747
1903
  this.errors = errors;
1748
1904
  this.method = options.method;
1749
1905
  this.path = options.path === undefined ? undefined : redactPath(options.path);
@@ -1781,19 +1937,23 @@ async function abortable(promise, signal, path) {
1781
1937
  }
1782
1938
 
1783
1939
  // packages/rest/src/route.ts
1940
+ import { createHash } from "crypto";
1784
1941
  function normalizeRoutePath(path) {
1785
1942
  const queryIndex = path.indexOf("?");
1786
1943
  const routePath = queryIndex === -1 ? path : path.slice(0, queryIndex);
1787
- return routePath.replace(/\/\d+(?=\/|$)/g, "/:id");
1944
+ return redactPath(routePath).replace(/\/\d+(?=\/|$)/g, "/:id");
1788
1945
  }
1789
1946
  function majorParameter(path) {
1790
- const match = /^\/(channels|guilds|webhooks)\/(\d+)(?:\/([^/?]+))?/.exec(path);
1947
+ const match = /^\/(channels|guilds|webhooks)\/(\d+)(?:\/([^/?]+))?/i.exec(path);
1791
1948
  if (!match)
1792
1949
  return "@none";
1793
- if (match[1] === "webhooks" && match[3] !== undefined)
1794
- return `${match[2]}:${match[3]}`;
1950
+ if (match[1].toLowerCase() === "webhooks" && match[3] !== undefined)
1951
+ return `${match[2]}:${tokenDigest(match[3])}`;
1795
1952
  return match[2];
1796
1953
  }
1954
+ function tokenDigest(token) {
1955
+ return createHash("sha256").update(token).digest("hex").slice(0, 16);
1956
+ }
1797
1957
  function scopeBucket(hashOrRoute, major) {
1798
1958
  return `${hashOrRoute}|${major}`;
1799
1959
  }
@@ -2035,6 +2195,9 @@ var Routes = {
2035
2195
  user: () => "/users/@me",
2036
2196
  userById: (userId) => `/users/${snowflake(userId, "User ID")}`,
2037
2197
  guild: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}`,
2198
+ currentUserGuild: (guildId) => `/users/@me/guilds/${snowflake(guildId, "Guild ID")}`,
2199
+ sticker: (stickerId) => `/stickers/${snowflake(stickerId, "Sticker ID")}`,
2200
+ messageReactionUser: (channelId, messageId, emoji, userId) => `${Routes.messageReactions(channelId, messageId, emoji)}/${snowflake(userId, "User ID")}`,
2038
2201
  guildPreview: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/preview`,
2039
2202
  guildActiveThreads: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/threads/active`,
2040
2203
  guildWebhooks: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/webhooks`,
@@ -2052,6 +2215,8 @@ var Routes = {
2052
2215
  crosspostMessage: (channelId, messageId) => `${Routes.message(channelId, messageId)}/crosspost`,
2053
2216
  messageReactions: (channelId, messageId, emoji) => `${Routes.message(channelId, messageId)}/reactions/${encodeURIComponent(emoji)}`,
2054
2217
  messageReactionsAll: (channelId, messageId) => `${Routes.message(channelId, messageId)}/reactions`,
2218
+ channelMessagesPins: (channelId) => `/channels/${snowflake(channelId, "Channel ID")}/messages/pins`,
2219
+ channelMessagesPin: (channelId, messageId) => `/channels/${snowflake(channelId, "Channel ID")}/messages/pins/${snowflake(messageId, "Message ID")}`,
2055
2220
  channelPins: (channelId) => `/channels/${snowflake(channelId, "Channel ID")}/pins`,
2056
2221
  channelPin: (channelId, messageId) => `/channels/${snowflake(channelId, "Channel ID")}/pins/${snowflake(messageId, "Message ID")}`,
2057
2222
  messageThread: (channelId, messageId) => `${Routes.message(channelId, messageId)}/threads`,
@@ -2110,6 +2275,44 @@ function snowflake(value, field) {
2110
2275
  throw new TypeError(`${field} must be a valid Discord snowflake.`);
2111
2276
  return value;
2112
2277
  }
2278
+ // packages/rest/src/error-codes.ts
2279
+ var RESTErrorCode = {
2280
+ UnknownAccount: 10001,
2281
+ UnknownChannel: 10003,
2282
+ UnknownGuild: 10004,
2283
+ UnknownInvite: 10006,
2284
+ UnknownMember: 10007,
2285
+ UnknownMessage: 10008,
2286
+ UnknownPermissionOverwrite: 10009,
2287
+ UnknownRole: 10011,
2288
+ UnknownUser: 10013,
2289
+ UnknownEmoji: 10014,
2290
+ UnknownWebhook: 10015,
2291
+ UnknownBan: 10026,
2292
+ UnknownSticker: 10060,
2293
+ UnknownInteraction: 10062,
2294
+ UnknownScheduledEvent: 10070,
2295
+ BotsCannotUseEndpoint: 20001,
2296
+ MaxGuilds: 30001,
2297
+ MaxPins: 30003,
2298
+ MaxRoles: 30005,
2299
+ MaxWebhooks: 30007,
2300
+ MaxEmojis: 30008,
2301
+ MaxReactions: 30010,
2302
+ MaxChannels: 30013,
2303
+ InteractionAlreadyAcknowledged: 40060,
2304
+ MissingAccess: 50001,
2305
+ CannotExecuteInDM: 50003,
2306
+ CannotEditOthersMessage: 50005,
2307
+ CannotSendEmptyMessage: 50006,
2308
+ CannotSendMessagesToUser: 50007,
2309
+ MissingPermissions: 50013,
2310
+ InvalidToken: 50014,
2311
+ MessageTooOldToBulkDelete: 50034,
2312
+ InvalidFormBody: 50035,
2313
+ ThreadArchived: 50083,
2314
+ CannotReplyWithoutReadHistory: 160002
2315
+ };
2113
2316
  // packages/rest/src/redis.ts
2114
2317
  var RESERVE_SCRIPT = `
2115
2318
  local raw = redis.call('GET', KEYS[1])
@@ -2256,7 +2459,7 @@ class WebhookClient {
2256
2459
  #rest;
2257
2460
  constructor(options, restOptions) {
2258
2461
  if (options.url) {
2259
- const match = options.url.match(/discord(?:app)?.com\/api\/webhooks\/(\d+)\/([A-Za-z0-9_-]+)/);
2462
+ const match = options.url.match(/^https:\/\/(?:(?:ptb|canary)\.)?discord(?:app)?\.com\/api(?:\/v\d+)?\/webhooks\/(\d{1,20})\/([A-Za-z0-9_-]+)\/?(?:[?#].*)?$/);
2260
2463
  if (!match)
2261
2464
  throw new Error("Invalid Discord webhook URL format.");
2262
2465
  this.id = match[1];
@@ -2271,13 +2474,20 @@ class WebhookClient {
2271
2474
  }
2272
2475
  async send(options) {
2273
2476
  const payload = typeof options === "string" ? { content: options } : options;
2274
- const { thread_id, ...body } = payload;
2275
- const query = thread_id ? `?thread_id=${thread_id}&wait=true` : `?wait=true`;
2477
+ const { thread_id, files, ...body } = payload;
2478
+ const params = new URLSearchParams({ wait: "true" });
2479
+ if (thread_id)
2480
+ params.set("thread_id", String(thread_id));
2481
+ const query = `?${params}`;
2276
2482
  const formattedEmbeds = body.embeds?.map((e) => ("toJSON" in e) ? e.toJSON() : e);
2277
- return this.#rest.post(`${Routes.webhook(this.id, this.token)}${query}`, {
2483
+ const formattedComponents = body.components?.map((c) => ("toJSON" in c) ? c.toJSON() : c);
2484
+ const path = `${Routes.webhook(this.id, this.token)}${query}`;
2485
+ const json = {
2278
2486
  ...body,
2279
- embeds: formattedEmbeds
2280
- });
2487
+ embeds: formattedEmbeds,
2488
+ components: formattedComponents
2489
+ };
2490
+ return files?.length ? this.#rest.postWithFiles(path, json, files) : this.#rest.post(path, json);
2281
2491
  }
2282
2492
  async editMessage(messageId, options) {
2283
2493
  const payload = typeof options === "string" ? { content: options } : options;
@@ -2291,7 +2501,23 @@ class WebhookClient {
2291
2501
  // packages/rest/src/index.ts
2292
2502
  var LIBRARY_VERSION = package_default.version;
2293
2503
  var LIBRARY_URL = "https://github.com/Ekretos/lunibee";
2294
- var USER_AGENT = `DiscordBot (${LIBRARY_URL}, ${package_default.version})`;
2504
+ var USER_AGENT = `DiscordBot (${LIBRARY_URL}, ${LIBRARY_VERSION})`;
2505
+ function assertSafePath(path) {
2506
+ const end = path.search(/[?#]/);
2507
+ const pathname = end === -1 ? path : path.slice(0, end);
2508
+ if (pathname.includes("\\"))
2509
+ throw new TypeError("REST paths must not contain backslashes.");
2510
+ for (const segment of pathname.split("/")) {
2511
+ let decoded;
2512
+ try {
2513
+ decoded = decodeURIComponent(segment);
2514
+ } catch {
2515
+ throw new TypeError("REST path has malformed percent-encoding.");
2516
+ }
2517
+ if (decoded === "." || decoded === "..")
2518
+ throw new TypeError("REST paths must not contain '.' or '..' segments.");
2519
+ }
2520
+ }
2295
2521
  var REQUEST_DATA_KEYS = new Set([
2296
2522
  "body",
2297
2523
  "files",
@@ -2376,6 +2602,7 @@ class REST {
2376
2602
  throw new TypeError("REST method is required.");
2377
2603
  if (!path.startsWith("/"))
2378
2604
  throw new TypeError("REST paths must start with '/'.");
2605
+ assertSafePath(path);
2379
2606
  const route = createRouteKey(method, path);
2380
2607
  const files = options.files;
2381
2608
  if (files && files.length > 0 && !(body instanceof FormData))
@@ -2463,13 +2690,19 @@ class REST {
2463
2690
  #headers(body, options) {
2464
2691
  const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
2465
2692
  const headers = { ...options.headers };
2693
+ const set = (name, value) => {
2694
+ for (const key of Object.keys(headers))
2695
+ if (key.toLowerCase() === name.toLowerCase())
2696
+ delete headers[key];
2697
+ headers[name] = value;
2698
+ };
2466
2699
  if (options.auth !== false && this.#token)
2467
- headers["Authorization"] = `Bot ${this.#token}`;
2468
- headers["User-Agent"] = USER_AGENT;
2700
+ set("Authorization", `Bot ${this.#token}`);
2701
+ set("User-Agent", USER_AGENT);
2469
2702
  if (options.reason !== undefined)
2470
- headers["X-Audit-Log-Reason"] = encodeURIComponent(options.reason);
2703
+ set("X-Audit-Log-Reason", encodeURIComponent(options.reason));
2471
2704
  if (!isFormData)
2472
- headers["Content-Type"] = "application/json";
2705
+ set("Content-Type", "application/json");
2473
2706
  return headers;
2474
2707
  }
2475
2708
  #encodeBody(body) {
@@ -2545,7 +2778,7 @@ function cdnURL(path, hash, options = {}) {
2545
2778
  const isAnimated = hash.startsWith("a_") && !options.forceStatic;
2546
2779
  const ext = options.extension ?? (isAnimated ? "gif" : "png");
2547
2780
  const size = options.size ? `?size=${options.size}` : "";
2548
- return `${CDN_BASE}${path}/${hash}.${ext}${size}`;
2781
+ return `${CDN_BASE}${path}/${encodeURIComponent(hash)}.${ext}${size}`;
2549
2782
  }
2550
2783
 
2551
2784
  class User extends BaseStructure {
@@ -2614,13 +2847,13 @@ class Channel extends BaseStructure {
2614
2847
  this.permissionOverwrites = (data.permission_overwrites ?? []).map((overwrite) => ({ ...overwrite }));
2615
2848
  this.#context = context;
2616
2849
  }
2617
- sendMessage(options) {
2850
+ send(options) {
2618
2851
  if (!this.#context)
2619
2852
  throw new Error("This channel is not attached to a client.");
2620
2853
  return this.#context.sendMessage(this.id, options);
2621
2854
  }
2622
- send(options) {
2623
- return this.sendMessage(options);
2855
+ sendMessage(options) {
2856
+ return this.send(options);
2624
2857
  }
2625
2858
  edit(options) {
2626
2859
  if (!this.#context?.editChannel)
@@ -2643,10 +2876,10 @@ class Channel extends BaseStructure {
2643
2876
  editParent(parentId) {
2644
2877
  return this.edit({ parent_id: parentId });
2645
2878
  }
2646
- delete() {
2879
+ delete(reason) {
2647
2880
  if (!this.#context?.deleteChannel)
2648
2881
  throw new Error("This channel is not attached to a client.");
2649
- return this.#context.deleteChannel(this.id);
2882
+ return this.#context.deleteChannel(this.id, reason);
2650
2883
  }
2651
2884
  update(options) {
2652
2885
  return this.edit(options);
@@ -2693,6 +2926,15 @@ class Guild extends BaseStructure {
2693
2926
  mfaLevel;
2694
2927
  explicitContentFilter;
2695
2928
  defaultMessageNotifications;
2929
+ afkChannelId;
2930
+ afkTimeout;
2931
+ widgetEnabled;
2932
+ widgetChannelId;
2933
+ applicationId;
2934
+ publicUpdatesChannelId;
2935
+ safetyAlertsChannelId;
2936
+ maxPresences;
2937
+ maxVideoChannelUsers;
2696
2938
  constructor(data) {
2697
2939
  super(data.id);
2698
2940
  if (!data.name)
@@ -2714,14 +2956,22 @@ class Guild extends BaseStructure {
2714
2956
  this.vanityUrlCode = data.vanity_url_code ?? null;
2715
2957
  this.nsfwLevel = data.nsfw_level ?? 0;
2716
2958
  this.discoverySplash = data.discovery_splash ?? null;
2717
- const d = data;
2718
- this.rulesChannelId = d.rules_channel_id ?? null;
2719
- this.systemChannelId = d.system_channel_id ?? null;
2720
- this.systemChannelFlags = d.system_channel_flags ?? 0;
2721
- this.maxMembers = d.max_members ?? 0;
2722
- this.mfaLevel = d.mfa_level ?? 0;
2723
- this.explicitContentFilter = d.explicit_content_filter ?? 0;
2724
- this.defaultMessageNotifications = d.default_message_notifications ?? 0;
2959
+ this.rulesChannelId = data.rules_channel_id ?? null;
2960
+ this.systemChannelId = data.system_channel_id ?? null;
2961
+ this.systemChannelFlags = data.system_channel_flags ?? 0;
2962
+ this.maxMembers = data.max_members ?? 0;
2963
+ this.mfaLevel = data.mfa_level ?? 0;
2964
+ this.explicitContentFilter = data.explicit_content_filter ?? 0;
2965
+ this.defaultMessageNotifications = data.default_message_notifications ?? 0;
2966
+ this.afkChannelId = data.afk_channel_id ?? null;
2967
+ this.afkTimeout = data.afk_timeout;
2968
+ this.widgetEnabled = data.widget_enabled ?? false;
2969
+ this.widgetChannelId = data.widget_channel_id ?? null;
2970
+ this.applicationId = data.application_id ?? null;
2971
+ this.publicUpdatesChannelId = data.public_updates_channel_id ?? null;
2972
+ this.safetyAlertsChannelId = data.safety_alerts_channel_id ?? null;
2973
+ this.maxPresences = data.max_presences ?? null;
2974
+ this.maxVideoChannelUsers = data.max_video_channel_users;
2725
2975
  }
2726
2976
  iconURL(options = {}) {
2727
2977
  if (!this.icon)
@@ -2818,10 +3068,10 @@ class GuildMember {
2818
3068
  get permissions() {
2819
3069
  if (this.#suppliedPermissions)
2820
3070
  return this.#suppliedPermissions;
2821
- return new PermissionsBitField(this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds) ?? 0n);
3071
+ return new PermissionsBitField(this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds, undefined, this.timedOutUntil) ?? 0n);
2822
3072
  }
2823
3073
  permissionsIn(channelId) {
2824
- const computed = this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds, channelId);
3074
+ const computed = this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds, channelId, this.timedOutUntil);
2825
3075
  return computed ? new PermissionsBitField(computed) : null;
2826
3076
  }
2827
3077
  #action(name) {
@@ -3257,6 +3507,13 @@ var OptionType = {
3257
3507
  class CommandOptions {
3258
3508
  #options;
3259
3509
  #resolved;
3510
+ #lookup(kind, id) {
3511
+ const group = this.#resolved?.[kind];
3512
+ if (typeof group !== "object" || group === null)
3513
+ return;
3514
+ const entry = group[id];
3515
+ return typeof entry === "object" && entry !== null ? entry : undefined;
3516
+ }
3260
3517
  constructor(options, resolved = {}) {
3261
3518
  let currentOptions = options;
3262
3519
  let group = null;
@@ -3345,7 +3602,7 @@ class CommandOptions {
3345
3602
  return null;
3346
3603
  }
3347
3604
  const userId = String(opt.value);
3348
- const resolved = this.#resolved?.users?.[userId] ?? null;
3605
+ const resolved = this.#lookup("users", userId) ?? null;
3349
3606
  if (!resolved && required)
3350
3607
  throw new TypeError(`Resolved user for option "${name}" is missing.`);
3351
3608
  return resolved;
@@ -3358,7 +3615,7 @@ class CommandOptions {
3358
3615
  return null;
3359
3616
  }
3360
3617
  const channelId = String(opt.value);
3361
- const resolved = this.#resolved?.channels?.[channelId] ?? null;
3618
+ const resolved = this.#lookup("channels", channelId) ?? null;
3362
3619
  if (!resolved && required)
3363
3620
  throw new TypeError(`Resolved channel for option "${name}" is missing.`);
3364
3621
  return resolved;
@@ -3371,7 +3628,7 @@ class CommandOptions {
3371
3628
  return null;
3372
3629
  }
3373
3630
  const roleId = String(opt.value);
3374
- const resolved = this.#resolved?.roles?.[roleId] ?? null;
3631
+ const resolved = this.#lookup("roles", roleId) ?? null;
3375
3632
  if (!resolved && required)
3376
3633
  throw new TypeError(`Resolved role for option "${name}" is missing.`);
3377
3634
  return resolved;
@@ -3384,7 +3641,7 @@ class CommandOptions {
3384
3641
  return null;
3385
3642
  }
3386
3643
  const id = String(opt.value);
3387
- const resolved = this.#resolved?.users?.[id] ?? this.#resolved?.roles?.[id] ?? null;
3644
+ const resolved = this.#lookup("users", id) ?? this.#lookup("roles", id) ?? null;
3388
3645
  if (!resolved && required)
3389
3646
  throw new TypeError(`Resolved mentionable for option "${name}" is missing.`);
3390
3647
  return resolved;
@@ -3394,9 +3651,9 @@ class CommandOptions {
3394
3651
  if (!opt || opt.type !== OptionType.Mentionable)
3395
3652
  return null;
3396
3653
  const id = String(opt.value);
3397
- if (this.#resolved?.users?.[id])
3654
+ if (this.#lookup("users", id))
3398
3655
  return "user";
3399
- if (this.#resolved?.roles?.[id])
3656
+ if (this.#lookup("roles", id))
3400
3657
  return "role";
3401
3658
  return null;
3402
3659
  }
@@ -3408,7 +3665,7 @@ class CommandOptions {
3408
3665
  return null;
3409
3666
  }
3410
3667
  const attachmentId = String(opt.value);
3411
- const resolved = this.#resolved?.attachments?.[attachmentId] ?? null;
3668
+ const resolved = this.#lookup("attachments", attachmentId) ?? null;
3412
3669
  if (!resolved && required)
3413
3670
  throw new TypeError(`Resolved attachment for option "${name}" is missing.`);
3414
3671
  return resolved;
@@ -3712,16 +3969,19 @@ class ContextMenuCommandInteraction extends CommandInteraction {
3712
3969
 
3713
3970
  class ComponentInteraction extends Interaction {
3714
3971
  get customId() {
3715
- return this.data?.data?.custom_id ?? "";
3972
+ const id = this.data.data?.custom_id;
3973
+ return typeof id === "string" ? id : "";
3716
3974
  }
3717
3975
  get messageId() {
3718
- return this.data?.message?.id;
3976
+ return this.data.message?.id;
3719
3977
  }
3720
3978
  get componentType() {
3721
- return this.data?.data?.component_type ?? 0;
3979
+ const type = this.data.data?.component_type;
3980
+ return typeof type === "number" ? type : 0;
3722
3981
  }
3723
3982
  get values() {
3724
- return this.data?.data?.values ?? [];
3983
+ const values = this.data.data?.values;
3984
+ return Array.isArray(values) ? values : [];
3725
3985
  }
3726
3986
  async deferUpdate(options = {}) {
3727
3987
  const withResponse = options.withResponse === true;
@@ -3733,10 +3993,11 @@ class ComponentInteraction extends Interaction {
3733
3993
 
3734
3994
  class ModalSubmitInteraction extends Interaction {
3735
3995
  get customId() {
3736
- return this.data?.data?.custom_id ?? "";
3996
+ const id = this.data.data?.custom_id;
3997
+ return typeof id === "string" ? id : "";
3737
3998
  }
3738
3999
  getInputValue(customId) {
3739
- const rows = this.data?.data?.components ?? [];
4000
+ const rows = this.data.data?.components ?? [];
3740
4001
  for (const row of rows) {
3741
4002
  for (const comp of row.components ?? []) {
3742
4003
  if (comp.custom_id === customId)
@@ -3760,11 +4021,12 @@ class AutocompleteInteraction extends Interaction {
3760
4021
  this.options = new CommandOptions(data.data?.options ?? []);
3761
4022
  }
3762
4023
  get commandName() {
3763
- return this.data?.data?.name ?? "";
4024
+ const name = this.data.data?.name;
4025
+ return typeof name === "string" ? name : "";
3764
4026
  }
3765
4027
  get focusedOption() {
3766
- const options = this.data?.data?.options ?? [];
3767
- return findFocused(options);
4028
+ const options = this.data.data?.options;
4029
+ return findFocused(Array.isArray(options) ? options : []);
3768
4030
  }
3769
4031
  async respond(choices) {
3770
4032
  if (!Array.isArray(choices))
@@ -4048,10 +4310,10 @@ class Message extends BaseStructure {
4048
4310
  update(options) {
4049
4311
  return this.edit(options);
4050
4312
  }
4051
- delete() {
4313
+ delete(reason) {
4052
4314
  if (!this.#context)
4053
4315
  throw new Error("This message is not attached to a client.");
4054
- return this.#context.deleteMessage(this.channelId, this.id);
4316
+ return this.#context.deleteMessage(this.channelId, this.id, reason);
4055
4317
  }
4056
4318
  reply(options) {
4057
4319
  if (!this.#context)
@@ -4098,15 +4360,15 @@ class Message extends BaseStructure {
4098
4360
  throw new Error("This message is not attached to a client.");
4099
4361
  return this.#context.removeAllReactions(this.channelId, this.id);
4100
4362
  }
4101
- pin() {
4363
+ pin(reason) {
4102
4364
  if (!this.#context?.pinMessage)
4103
4365
  throw new Error("This message is not attached to a client.");
4104
- return this.#context.pinMessage(this.channelId, this.id);
4366
+ return this.#context.pinMessage(this.channelId, this.id, reason);
4105
4367
  }
4106
- unpin() {
4368
+ unpin(reason) {
4107
4369
  if (!this.#context?.unpinMessage)
4108
4370
  throw new Error("This message is not attached to a client.");
4109
- return this.#context.unpinMessage(this.channelId, this.id);
4371
+ return this.#context.unpinMessage(this.channelId, this.id, reason);
4110
4372
  }
4111
4373
  get isEphemeral() {
4112
4374
  return (this.flags & 64) !== 0;
@@ -4260,7 +4522,7 @@ class UserManager extends ResourceManager {
4260
4522
  return this.upsert(new User(data));
4261
4523
  }
4262
4524
  async leaveGuild(guildId) {
4263
- await this.#rest.delete(`/users/@me/guilds/${guildId}`);
4525
+ await this.#rest.delete(Routes.currentUserGuild(guildId));
4264
4526
  }
4265
4527
  async createDM(userId) {
4266
4528
  return this.#rest.post("/users/@me/channels", {
@@ -4285,15 +4547,22 @@ class EmojiManager extends Manager {
4285
4547
  return data.map((item) => this.upsert(item));
4286
4548
  }
4287
4549
  async create(options) {
4288
- return this.upsert(await this.#rest.post(Routes.guildEmoji(this.#guildId), options));
4550
+ const [payload, reason] = splitReason(options);
4551
+ return this.upsert(await this.#rest.post(Routes.guildEmoji(this.#guildId), payload, { reason }));
4289
4552
  }
4290
4553
  async edit(emojiId, options) {
4291
- return this.upsert(await this.#rest.patch(Routes.guildEmoji(this.#guildId, emojiId), options));
4554
+ const [payload, reason] = splitReason(options);
4555
+ return this.upsert(await this.#rest.patch(Routes.guildEmoji(this.#guildId, emojiId), payload, { reason }));
4292
4556
  }
4293
- async deleteEmoji(emojiId) {
4294
- await this.#rest.delete(Routes.guildEmoji(this.#guildId, emojiId));
4557
+ async remove(emojiId, reason) {
4558
+ await this.#rest.delete(Routes.guildEmoji(this.#guildId, emojiId), {
4559
+ reason
4560
+ });
4295
4561
  this.delete(emojiId);
4296
4562
  }
4563
+ deleteEmoji(emojiId) {
4564
+ return this.remove(emojiId);
4565
+ }
4297
4566
  upsert(data) {
4298
4567
  const key = data.id != null ? data.id : `unicode:${data.name ?? ""}`;
4299
4568
  return this.#merge(key, new Emoji(data));
@@ -4497,11 +4766,16 @@ class GuildMemberManager extends ResourceManager {
4497
4766
  await this.#rest.put(Routes.guildBan(this.guildId, userId), { delete_message_seconds: options.deleteMessageSeconds }, { reason: options.reason });
4498
4767
  this.delete(userId);
4499
4768
  }
4500
- async unban(userId) {
4501
- await this.#rest.delete(Routes.guildBan(this.guildId, userId));
4769
+ async unban(userId, reason) {
4770
+ await this.#rest.delete(Routes.guildBan(this.guildId, userId), {
4771
+ reason
4772
+ });
4502
4773
  }
4503
4774
  async edit(userId, options, reason) {
4504
- const data = await this.#rest.patch(Routes.guildMember(this.guildId, userId), options, { reason });
4775
+ const [payload, optionsReason] = splitReason(options);
4776
+ const data = await this.#rest.patch(Routes.guildMember(this.guildId, userId), payload, {
4777
+ reason: optionsReason ?? reason
4778
+ });
4505
4779
  const member = new GuildMember({ ...data, guild_id: this.guildId }, this.#context());
4506
4780
  this.set(member.user.id, member);
4507
4781
  return member;
@@ -4537,28 +4811,43 @@ class RoleManager extends ResourceManager {
4537
4811
  }
4538
4812
  async create(options) {
4539
4813
  const { reason, ...payload } = options;
4540
- const data = await this.#rest.post(Routes.guildRoles(this.guildId), {
4541
- ...payload,
4542
- permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
4543
- });
4544
- const role = new Role(data);
4545
- this.set(role.id, role);
4546
- return role;
4814
+ const data = await this.#rest.post(Routes.guildRoles(this.guildId), rolePayload(payload), { reason });
4815
+ return this.#store(data);
4547
4816
  }
4548
4817
  async edit(roleId, options) {
4549
4818
  const { reason, ...payload } = options;
4550
- const data = await this.#rest.patch(Routes.guildRole(this.guildId, roleId), {
4551
- ...payload,
4552
- permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
4553
- });
4819
+ const data = await this.#rest.patch(Routes.guildRole(this.guildId, roleId), rolePayload(payload), { reason });
4820
+ return this.#store(data);
4821
+ }
4822
+ #store(data) {
4554
4823
  const role = new Role(data);
4555
4824
  this.set(role.id, role);
4556
4825
  return role;
4557
4826
  }
4558
- async deleteRole(roleId) {
4559
- await this.#rest.delete(Routes.guildRole(this.guildId, roleId));
4827
+ async remove(roleId, reason) {
4828
+ await this.#rest.delete(Routes.guildRole(this.guildId, roleId), {
4829
+ reason
4830
+ });
4560
4831
  this.delete(roleId);
4561
4832
  }
4833
+ async setPositions(positions, reason) {
4834
+ const data = await this.#rest.patch(Routes.guildRoles(this.guildId), positions.map(({ id, position }) => ({ id, position })), { reason });
4835
+ return data.map((item) => {
4836
+ const role = new Role(item);
4837
+ this.set(role.id, role);
4838
+ return role;
4839
+ });
4840
+ }
4841
+ deleteRole(roleId) {
4842
+ return this.remove(roleId);
4843
+ }
4844
+ }
4845
+ function rolePayload(options) {
4846
+ const { permissions, ...rest } = options;
4847
+ return {
4848
+ ...rest,
4849
+ permissions: permissions !== undefined ? String(permissions) : undefined
4850
+ };
4562
4851
  }
4563
4852
 
4564
4853
  // packages/managers/src/guild-resources.ts
@@ -4630,13 +4919,15 @@ class GuildScheduledEventManager extends Manager {
4630
4919
  return events.map((event) => this.#store(event));
4631
4920
  }
4632
4921
  async create(options, reason) {
4633
- return this.#store(await this.#rest.post(Routes.guildScheduledEvents(this.guildId), options, { reason }));
4922
+ const [payload, optionsReason] = splitReason(options);
4923
+ return this.#store(await this.#rest.post(Routes.guildScheduledEvents(this.guildId), payload, { reason: optionsReason ?? reason }));
4634
4924
  }
4635
4925
  async edit(eventId, options, reason) {
4636
- return this.#store(await this.#rest.patch(Routes.guildScheduledEvent(this.guildId, eventId), options, { reason }));
4926
+ const [payload, optionsReason] = splitReason(options);
4927
+ return this.#store(await this.#rest.patch(Routes.guildScheduledEvent(this.guildId, eventId), payload, { reason: optionsReason ?? reason }));
4637
4928
  }
4638
- async remove(eventId) {
4639
- await this.#rest.delete(Routes.guildScheduledEvent(this.guildId, eventId));
4929
+ async remove(eventId, reason) {
4930
+ await this.#rest.delete(Routes.guildScheduledEvent(this.guildId, eventId), { reason });
4640
4931
  this.delete(eventId);
4641
4932
  }
4642
4933
  async fetchSubscribers(eventId, options = {}) {
@@ -4667,13 +4958,13 @@ class StageInstanceManager extends Manager {
4667
4958
  privacy_level: options.privacyLevel,
4668
4959
  send_start_notification: options.sendStartNotification,
4669
4960
  guild_scheduled_event_id: options.guildScheduledEventId
4670
- }, { reason }));
4961
+ }, { reason: options.reason ?? reason }));
4671
4962
  }
4672
4963
  async fetch(channelId) {
4673
4964
  return this.#store(await this.#rest.get(Routes.stageInstanceByChannel(channelId)));
4674
4965
  }
4675
4966
  async edit(channelId, options, reason) {
4676
- return this.#store(await this.#rest.patch(Routes.stageInstanceByChannel(channelId), { topic: options.topic, privacy_level: options.privacyLevel }, { reason }));
4967
+ return this.#store(await this.#rest.patch(Routes.stageInstanceByChannel(channelId), { topic: options.topic, privacy_level: options.privacyLevel }, { reason: options.reason ?? reason }));
4677
4968
  }
4678
4969
  async remove(channelId, reason) {
4679
4970
  await this.#rest.delete(Routes.stageInstanceByChannel(channelId), {
@@ -4710,7 +5001,7 @@ class PermissionOverwriteManager {
4710
5001
  type: options.type,
4711
5002
  allow: BigInt(options.allow ?? 0).toString(),
4712
5003
  deny: BigInt(options.deny ?? 0).toString()
4713
- }, { reason });
5004
+ }, { reason: options.reason ?? reason });
4714
5005
  }
4715
5006
  async remove(overwriteId, reason) {
4716
5007
  await this.#rest.delete(Routes.channelPermission(this.channelId, overwriteId), { reason });
@@ -4828,12 +5119,16 @@ class GuildManager extends ResourceManager {
4828
5119
  return this.upsert(new Guild(data));
4829
5120
  }
4830
5121
  async edit(id, options) {
4831
- const data = await this.#rest.patch(Routes.guild(id), options);
5122
+ const [payload, reason] = splitReason(options);
5123
+ const data = await this.#rest.patch(Routes.guild(id), payload, { reason });
4832
5124
  return this.upsert(new Guild(data));
4833
5125
  }
4834
- async deleteGuild(id) {
5126
+ async remove(id) {
4835
5127
  await this.#rest.delete(Routes.guild(id));
4836
5128
  }
5129
+ deleteGuild(id) {
5130
+ return this.remove(id);
5131
+ }
4837
5132
  async fetchPreview(id) {
4838
5133
  return this.#rest.get(Routes.guildPreview(id));
4839
5134
  }
@@ -4877,15 +5172,17 @@ class GuildManager extends ResourceManager {
4877
5172
  return new AutoModerationRule(rule);
4878
5173
  }
4879
5174
  async createAutoModerationRule(guildId, options) {
4880
- const rule = await this.#rest.post(Routes.guildAutoModerationRules(guildId), options);
5175
+ const [payload, reason] = splitReason(options);
5176
+ const rule = await this.#rest.post(Routes.guildAutoModerationRules(guildId), payload, { reason });
4881
5177
  return new AutoModerationRule(rule);
4882
5178
  }
4883
5179
  async editAutoModerationRule(guildId, ruleId, options) {
4884
- const rule = await this.#rest.patch(Routes.guildAutoModerationRule(guildId, ruleId), options);
5180
+ const [payload, reason] = splitReason(options);
5181
+ const rule = await this.#rest.patch(Routes.guildAutoModerationRule(guildId, ruleId), payload, { reason });
4885
5182
  return new AutoModerationRule(rule);
4886
5183
  }
4887
- async deleteAutoModerationRule(guildId, ruleId) {
4888
- await this.#rest.delete(Routes.guildAutoModerationRule(guildId, ruleId));
5184
+ async deleteAutoModerationRule(guildId, ruleId, reason) {
5185
+ await this.#rest.delete(Routes.guildAutoModerationRule(guildId, ruleId), { reason });
4889
5186
  }
4890
5187
  }
4891
5188
  var AuditLogEvent = {
@@ -5001,16 +5298,16 @@ class ChannelManager extends Manager {
5001
5298
  this.#context = {
5002
5299
  sendMessage: (channelId, options) => this.send(channelId, options),
5003
5300
  editMessage: (channelId, messageId, options) => this.editMessage(channelId, messageId, options),
5004
- deleteMessage: (channelId, messageId) => this.deleteMessage(channelId, messageId),
5301
+ deleteMessage: (channelId, messageId, reason) => this.deleteMessage(channelId, messageId, reason),
5005
5302
  crosspostMessage: (channelId, messageId) => this.crosspostMessage(channelId, messageId),
5006
5303
  editChannel: (channelId, options) => this.edit(channelId, options),
5007
- deleteChannel: (channelId) => this.deleteChannel(channelId),
5304
+ deleteChannel: (channelId, reason) => this.remove(channelId, reason),
5008
5305
  addReaction: (channelId, messageId, emoji) => this.addReaction(channelId, messageId, emoji),
5009
5306
  removeOwnReaction: (channelId, messageId, emoji) => this.removeOwnReaction(channelId, messageId, emoji),
5010
5307
  removeReaction: (channelId, messageId, emoji, userId) => this.removeReaction(channelId, messageId, emoji, userId),
5011
5308
  removeAllReactions: (channelId, messageId) => this.removeAllReactions(channelId, messageId),
5012
- pinMessage: (channelId, messageId) => this.pinMessage(channelId, messageId),
5013
- unpinMessage: (channelId, messageId) => this.unpinMessage(channelId, messageId)
5309
+ pinMessage: (channelId, messageId, reason) => this.pinMessage(channelId, messageId, reason),
5310
+ unpinMessage: (channelId, messageId, reason) => this.unpinMessage(channelId, messageId, reason)
5014
5311
  };
5015
5312
  }
5016
5313
  messages(channelId) {
@@ -5080,15 +5377,20 @@ class ChannelManager extends Manager {
5080
5377
  return this.#messageManagers.get(channelId);
5081
5378
  }
5082
5379
  async create(guildId, options) {
5083
- return this.upsert(await this.#rest.post(Routes.guildChannels(guildId), options));
5380
+ const [payload, reason] = splitReason(options);
5381
+ return this.upsert(await this.#rest.post(Routes.guildChannels(guildId), payload, { reason }));
5084
5382
  }
5085
5383
  async edit(channelId, options) {
5086
- return this.upsert(await this.#rest.patch(Routes.channel(channelId), options));
5384
+ const [payload, reason] = splitReason(options);
5385
+ return this.upsert(await this.#rest.patch(Routes.channel(channelId), payload, { reason }));
5087
5386
  }
5088
- async deleteChannel(channelId) {
5089
- await this.#rest.delete(Routes.channel(channelId));
5387
+ async remove(channelId, reason) {
5388
+ await this.#rest.delete(Routes.channel(channelId), { reason });
5090
5389
  this.delete(channelId);
5091
5390
  }
5391
+ deleteChannel(channelId) {
5392
+ return this.remove(channelId);
5393
+ }
5092
5394
  delete(channelId) {
5093
5395
  this.#messageManagers.delete(channelId);
5094
5396
  return super.delete(channelId);
@@ -5124,8 +5426,10 @@ class ChannelManager extends Manager {
5124
5426
  async editMessage(channelId, messageId, options) {
5125
5427
  return this.messages(channelId).upsert(await this.#rest.patch(Routes.message(channelId, messageId), toRequest(options, this.#allowedMentions)));
5126
5428
  }
5127
- async deleteMessage(channelId, messageId) {
5128
- await this.#rest.delete(Routes.message(channelId, messageId));
5429
+ async deleteMessage(channelId, messageId, reason) {
5430
+ await this.#rest.delete(Routes.message(channelId, messageId), {
5431
+ reason
5432
+ });
5129
5433
  this.messages(channelId).delete(messageId);
5130
5434
  }
5131
5435
  deleteCachedMessage(channelId, messageId) {
@@ -5134,19 +5438,17 @@ class ChannelManager extends Manager {
5134
5438
  async crosspostMessage(channelId, messageId) {
5135
5439
  return this.messages(channelId).upsert(await this.#rest.post(Routes.crosspostMessage(channelId, messageId)));
5136
5440
  }
5137
- async bulkDeleteMessages(channelId, messageIds) {
5441
+ async bulkDeleteMessages(channelId, messageIds, reason) {
5138
5442
  const ids = [...new Set(messageIds)];
5139
5443
  if (ids.length < 1 || ids.length > 100)
5140
5444
  throw new RangeError("bulkDelete requires between 1 and 100 message IDs.");
5141
5445
  if (ids.length === 1)
5142
- return this.deleteMessage(channelId, ids[0]);
5446
+ return this.deleteMessage(channelId, ids[0], reason);
5143
5447
  const cutoff = Date.now() - BULK_DELETE_MAX_AGE_MS;
5144
5448
  const tooOld = ids.filter((id) => snowflakeTime(id) < cutoff);
5145
5449
  if (tooOld.length)
5146
5450
  throw new RangeError(`bulkDelete cannot delete messages older than 14 days: ${tooOld.join(", ")}`);
5147
- await this.#rest.post(Routes.channelBulkDelete(channelId), {
5148
- messages: ids
5149
- });
5451
+ await this.#rest.post(Routes.channelBulkDelete(channelId), { messages: ids }, { reason });
5150
5452
  for (const id of ids)
5151
5453
  this.messages(channelId).delete(id);
5152
5454
  }
@@ -5183,20 +5485,26 @@ class ChannelManager extends Manager {
5183
5485
  await this.#rest.delete(`${Routes.messageReactions(channelId, messageId, emoji)}/@me`);
5184
5486
  }
5185
5487
  async removeReaction(channelId, messageId, emoji, userId) {
5186
- await this.#rest.delete(`${Routes.messageReactions(channelId, messageId, emoji)}/${userId}`);
5488
+ await this.#rest.delete(Routes.messageReactionUser(channelId, messageId, emoji, userId));
5187
5489
  }
5188
5490
  async removeAllReactions(channelId, messageId) {
5189
5491
  await this.#rest.delete(Routes.messageReactionsAll(channelId, messageId));
5190
5492
  }
5191
5493
  async fetchPinnedMessages(channelId) {
5192
- const data = await this.#rest.get(Routes.channelPins(channelId));
5193
- return data.map((item) => this.messages(channelId).upsert(item));
5494
+ const data = await this.#rest.get(Routes.channelMessagesPins(channelId));
5495
+ return data.items.map((item) => this.messages(channelId).upsert(item.message));
5194
5496
  }
5195
- async pinMessage(channelId, messageId) {
5196
- await this.#rest.put(Routes.channelPin(channelId, messageId));
5497
+ async pinMessage(channelId, messageId, reason) {
5498
+ await this.#rest.put(Routes.channelMessagesPin(channelId, messageId), undefined, { reason });
5197
5499
  }
5198
- async unpinMessage(channelId, messageId) {
5199
- await this.#rest.delete(Routes.channelPin(channelId, messageId));
5500
+ async unpinMessage(channelId, messageId, reason) {
5501
+ await this.#rest.delete(Routes.channelMessagesPin(channelId, messageId), { reason });
5502
+ }
5503
+ async createWebhook(channelId, options) {
5504
+ const [payload, reason] = splitReason(options);
5505
+ return this.#rest.post(Routes.channelWebhooks(channelId), payload, {
5506
+ reason
5507
+ });
5200
5508
  }
5201
5509
  createThreadFromMessage(channelId, messageId, options) {
5202
5510
  return this.threads(channelId).createFromMessage(messageId, options);
@@ -5214,7 +5522,7 @@ class ChannelManager extends Manager {
5214
5522
  hasMore: messages.length === limit
5215
5523
  };
5216
5524
  }
5217
- async bulkDelete(channelId, messageIds) {
5525
+ bulkDelete(channelId, messageIds) {
5218
5526
  return this.bulkDeleteMessages(channelId, messageIds);
5219
5527
  }
5220
5528
  clear() {
@@ -5300,7 +5608,26 @@ class GatewaySession {
5300
5608
  return resume ? { type: "resume", ...resume } : { type: "identify" };
5301
5609
  }
5302
5610
  connectURL(fallback) {
5303
- return this.resumeInfo()?.resumeURL ?? fallback;
5611
+ const resume = this.resumeInfo()?.resumeURL;
5612
+ return resume !== undefined && isTrustedGatewayURL(resume, fallback) ? resume : fallback;
5613
+ }
5614
+ }
5615
+ function isTrustedGatewayURL(url, fallback) {
5616
+ let parsed;
5617
+ try {
5618
+ parsed = new URL(url);
5619
+ } catch {
5620
+ return false;
5621
+ }
5622
+ if (parsed.protocol !== "wss:" || parsed.username || parsed.password)
5623
+ return false;
5624
+ const host = parsed.hostname.toLowerCase();
5625
+ if (host === "discord.gg" || host.endsWith(".discord.gg"))
5626
+ return true;
5627
+ try {
5628
+ return host === new URL(fallback).hostname.toLowerCase();
5629
+ } catch {
5630
+ return false;
5304
5631
  }
5305
5632
  }
5306
5633
 
@@ -5576,12 +5903,15 @@ class PlainTextDecoder {
5576
5903
 
5577
5904
  class ZlibStreamDecoder {
5578
5905
  #create;
5906
+ #maxFrameBytes;
5579
5907
  #inflate;
5580
5908
  #chunks = [];
5909
+ #size = 0;
5581
5910
  #failure;
5582
5911
  #pendingReject;
5583
- constructor(create = () => createInflate()) {
5912
+ constructor(create = () => createInflate(), maxFrameBytes = 64 * 1024 * 1024) {
5584
5913
  this.#create = create;
5914
+ this.#maxFrameBytes = maxFrameBytes;
5585
5915
  }
5586
5916
  push(data) {
5587
5917
  if (typeof data === "string")
@@ -5600,6 +5930,7 @@ class ZlibStreamDecoder {
5600
5930
  await this.#awaiting((settle) => inflate.flush(zlibConstants.Z_SYNC_FLUSH, () => settle()));
5601
5931
  const parts = this.#chunks;
5602
5932
  this.#chunks = [];
5933
+ this.#size = 0;
5603
5934
  if (parts.length === 0)
5604
5935
  return [];
5605
5936
  const total = parts.reduce((size, part) => size + part.length, 0);
@@ -5615,6 +5946,7 @@ class ZlibStreamDecoder {
5615
5946
  const inflate = this.#inflate;
5616
5947
  this.#inflate = undefined;
5617
5948
  this.#chunks = [];
5949
+ this.#size = 0;
5618
5950
  this.#failure = undefined;
5619
5951
  this.#pendingReject = undefined;
5620
5952
  if (!inflate)
@@ -5642,7 +5974,17 @@ class ZlibStreamDecoder {
5642
5974
  }
5643
5975
  #open() {
5644
5976
  const inflate = this.#create();
5645
- inflate.on("data", (chunk) => this.#chunks.push(chunk));
5977
+ inflate.on("data", (chunk) => {
5978
+ if (this.#failure)
5979
+ return;
5980
+ this.#size += chunk.length;
5981
+ if (this.#size > this.#maxFrameBytes) {
5982
+ this.#chunks = [];
5983
+ inflate.emit("error", new Error(`Gateway frame inflated past ${this.#maxFrameBytes} bytes.`));
5984
+ return;
5985
+ }
5986
+ this.#chunks.push(chunk);
5987
+ });
5646
5988
  inflate.on("error", (error) => {
5647
5989
  this.#failure = error;
5648
5990
  const reject = this.#pendingReject;
@@ -5885,9 +6227,9 @@ function classifyPayload(payload) {
5885
6227
  }
5886
6228
  function identifyPayload(options) {
5887
6229
  const props = options.properties ?? {};
5888
- const os = props.os ?? "Android";
5889
- const browser = props.browser ?? "Discord Android";
5890
- const device = props.device ?? "Discord Android";
6230
+ const os = props.os ?? process.platform;
6231
+ const browser = props.browser ?? "Lunibee";
6232
+ const device = props.device ?? "Lunibee";
5891
6233
  return {
5892
6234
  op: GatewayOpcodes.Identify,
5893
6235
  d: {
@@ -6004,9 +6346,9 @@ class Gateway {
6004
6346
  heartbeatAckTimeout: 1e4,
6005
6347
  zombieTimeout: 30000,
6006
6348
  properties: {
6007
- os: "Android",
6008
- browser: "Discord Android",
6009
- device: "Discord Android"
6349
+ os: process.platform,
6350
+ browser: "Lunibee",
6351
+ device: "Lunibee"
6010
6352
  },
6011
6353
  presence: {
6012
6354
  status: "online",
@@ -6322,14 +6664,12 @@ class Gateway {
6322
6664
 
6323
6665
  // packages/core/src/index.ts
6324
6666
  class EventEmitter2 {
6325
- #listeners = new Map;
6667
+ #listeners = {};
6668
+ redactSecrets = (text) => text;
6326
6669
  on(event, listener) {
6327
6670
  if (typeof listener !== "function")
6328
6671
  throw new TypeError("Event listener must be a function.");
6329
- let listeners = this.#listeners.get(event);
6330
- if (!listeners)
6331
- this.#listeners.set(event, listeners = new Set);
6332
- listeners.add(listener);
6672
+ (this.#listeners[event] ??= new Set).add(listener);
6333
6673
  return this;
6334
6674
  }
6335
6675
  once(event, listener) {
@@ -6340,7 +6680,7 @@ class EventEmitter2 {
6340
6680
  return this.on(event, wrapped);
6341
6681
  }
6342
6682
  off(event, listener) {
6343
- this.#listeners.get(event)?.delete(listener);
6683
+ this.#listeners[event]?.delete(listener);
6344
6684
  return this;
6345
6685
  }
6346
6686
  removeListener(event, listener) {
@@ -6348,13 +6688,13 @@ class EventEmitter2 {
6348
6688
  }
6349
6689
  removeAllListeners(event) {
6350
6690
  if (event === undefined)
6351
- this.#listeners.clear();
6691
+ this.#listeners = {};
6352
6692
  else
6353
- this.#listeners.delete(event);
6693
+ delete this.#listeners[event];
6354
6694
  return this;
6355
6695
  }
6356
6696
  emit(event, ...args) {
6357
- const listeners = this.#listeners.get(event);
6697
+ const listeners = this.#listeners[event];
6358
6698
  if (!listeners?.size)
6359
6699
  return false;
6360
6700
  for (const listener of [...listeners]) {
@@ -6369,18 +6709,30 @@ class EventEmitter2 {
6369
6709
  return true;
6370
6710
  }
6371
6711
  #handleError(event, error) {
6372
- if (event === "error" /* Error */)
6373
- return;
6374
6712
  const normalized = error instanceof Error ? error : new Error(String(error), { cause: error });
6375
- for (const listener of [
6376
- ...this.#listeners.get("error" /* Error */) ?? []
6377
- ]) {
6713
+ const errorListeners = this.#listeners["error" /* Error */];
6714
+ const listeners = event === "error" /* Error */ ? [] : [...errorListeners ?? []];
6715
+ if (listeners.length === 0)
6716
+ return warnListenerError(event, normalized, this.redactSecrets);
6717
+ for (const listener of listeners) {
6378
6718
  try {
6379
- listener(normalized);
6380
- } catch {}
6719
+ const result = listener(normalized);
6720
+ if (result && typeof result.then === "function")
6721
+ Promise.resolve(result).catch((failure) => warnListenerError("error" /* Error */, failure, this.redactSecrets));
6722
+ } catch (failure) {
6723
+ warnListenerError("error" /* Error */, failure, this.redactSecrets);
6724
+ }
6381
6725
  }
6382
6726
  }
6383
6727
  }
6728
+ function warnListenerError(event, error, redact = (text) => text) {
6729
+ const failure = error instanceof Error ? error : new Error(String(error));
6730
+ process.emitWarning(redact(`A "${String(event)}" listener threw and no error listener handled it: ${failure.message}`), {
6731
+ type: "LunibeeWarning",
6732
+ code: "LUNIBEE_UNHANDLED_LISTENER_ERROR",
6733
+ detail: failure.stack === undefined ? undefined : redact(failure.stack)
6734
+ });
6735
+ }
6384
6736
 
6385
6737
  class Client extends EventEmitter2 {
6386
6738
  options;
@@ -6400,6 +6752,10 @@ class Client extends EventEmitter2 {
6400
6752
  user;
6401
6753
  readyAt;
6402
6754
  state = "idle";
6755
+ redactSecrets = (text) => {
6756
+ const token = this.options.token;
6757
+ return token && token.length >= 8 ? text.split(token).join("[token]") : text;
6758
+ };
6403
6759
  get token() {
6404
6760
  return this.state === "destroyed" ? null : this.options.token ?? null;
6405
6761
  }
@@ -6446,21 +6802,36 @@ class Client extends EventEmitter2 {
6446
6802
  this.stageInstances = new StageInstanceManager(this.rest);
6447
6803
  const placeholderAppCommands = new ApplicationCommandManager(this.rest, "0");
6448
6804
  this.application = { commands: placeholderAppCommands };
6449
- this.#resourceContext = {
6805
+ this.#resourceContext = this.#createResourceContext();
6806
+ this.guilds.attachContext(this.#resourceContext);
6807
+ this.#gateway = new Gateway({
6808
+ token: options.token,
6809
+ intents: options.intents,
6810
+ ...options.gateway
6811
+ });
6812
+ this.#wireLifecycle();
6813
+ this.#wireMessages();
6814
+ this.#wireGuilds();
6815
+ this.#wireGuildFeatures();
6816
+ this.#wireChannels();
6817
+ this.#wireMisc();
6818
+ }
6819
+ #createResourceContext() {
6820
+ return {
6450
6821
  sendMessage: (channelId, options) => this.channels.send(channelId, options),
6451
6822
  editMessage: (channelId, messageId, options) => this.channels.editMessage(channelId, messageId, options),
6452
- deleteMessage: (channelId, messageId) => this.channels.deleteMessage(channelId, messageId),
6823
+ deleteMessage: (channelId, messageId, reason) => this.channels.deleteMessage(channelId, messageId, reason),
6453
6824
  crosspostMessage: (channelId, messageId) => this.channels.crosspostMessage(channelId, messageId),
6454
6825
  editChannel: (channelId, options) => this.channels.edit(channelId, options),
6455
- deleteChannel: (channelId) => this.channels.deleteChannel(channelId),
6826
+ deleteChannel: (channelId, reason) => this.channels.remove(channelId, reason),
6456
6827
  addReaction: (channelId, messageId, emoji) => this.channels.addReaction(channelId, messageId, emoji),
6457
6828
  removeOwnReaction: (channelId, messageId, emoji) => this.channels.removeOwnReaction(channelId, messageId, emoji),
6458
6829
  removeReaction: (channelId, messageId, emoji, userId) => this.channels.removeReaction(channelId, messageId, emoji, userId),
6459
6830
  removeAllReactions: (channelId, messageId) => this.channels.removeAllReactions(channelId, messageId),
6460
- pinMessage: (channelId, messageId) => this.channels.pinMessage(channelId, messageId),
6461
- unpinMessage: (channelId, messageId) => this.channels.unpinMessage(channelId, messageId),
6831
+ pinMessage: (channelId, messageId, reason) => this.channels.pinMessage(channelId, messageId, reason),
6832
+ unpinMessage: (channelId, messageId, reason) => this.channels.unpinMessage(channelId, messageId, reason),
6462
6833
  collectInteractions: (options) => this.createCollector("interactionCreate" /* InteractionCreate */, options),
6463
- memberPermissions: (guildId, memberId, roleIds, channelId) => this.#memberPermissions(guildId, memberId, roleIds, channelId),
6834
+ memberPermissions: (guildId, memberId, roleIds, channelId, timedOutUntil) => this.#memberPermissions(guildId, memberId, roleIds, channelId, timedOutUntil),
6464
6835
  kickMember: (guildId, userId, reason) => this.guilds.members(guildId).kick(userId, reason),
6465
6836
  banMember: (guildId, userId, options) => this.guilds.members(guildId).ban(userId, options),
6466
6837
  editMember: (guildId, userId, options, reason) => this.guilds.members(guildId).edit(userId, options, reason),
@@ -6483,12 +6854,8 @@ class Client extends EventEmitter2 {
6483
6854
  return this.channels.permissionOverwrites(channelId).update(targetId, bits, options);
6484
6855
  }
6485
6856
  };
6486
- this.guilds.attachContext(this.#resourceContext);
6487
- this.#gateway = new Gateway({
6488
- token: options.token,
6489
- intents: options.intents,
6490
- ...options.gateway
6491
- });
6857
+ }
6858
+ #wireLifecycle() {
6492
6859
  this.#gateway.on("READY", (data) => {
6493
6860
  const ready = data;
6494
6861
  this.user = ready.user;
@@ -6514,6 +6881,8 @@ class Client extends EventEmitter2 {
6514
6881
  this.state = "idle";
6515
6882
  this.emit("close" /* Close */, data);
6516
6883
  });
6884
+ }
6885
+ #wireMessages() {
6517
6886
  this.#gateway.on("MESSAGE_CREATE", (data) => {
6518
6887
  const payload = data;
6519
6888
  const message = new Message(payload, this.#resourceContext);
@@ -6561,6 +6930,8 @@ class Client extends EventEmitter2 {
6561
6930
  this.#gateway.on("MESSAGE_REACTION_REMOVE_EMOJI", (data) => this.emit("messageReactionRemoveEmoji" /* MessageReactionRemoveEmoji */, data));
6562
6931
  this.#gateway.on("MESSAGE_POLL_VOTE_ADD", (data) => this.emit("messagePollVoteAdd" /* MessagePollVoteAdd */, data));
6563
6932
  this.#gateway.on("MESSAGE_POLL_VOTE_REMOVE", (data) => this.emit("messagePollVoteRemove" /* MessagePollVoteRemove */, data));
6933
+ }
6934
+ #wireGuilds() {
6564
6935
  this.#gateway.on("GUILD_CREATE", (data) => {
6565
6936
  const payload = data;
6566
6937
  if (payload.unavailable) {
@@ -6661,6 +7032,8 @@ class Client extends EventEmitter2 {
6661
7032
  roles.delete(event.role_id);
6662
7033
  this.emit("guildRoleDelete" /* GuildRoleDelete */, event, removed);
6663
7034
  });
7035
+ }
7036
+ #wireGuildFeatures() {
6664
7037
  this.#gateway.on("GUILD_EMOJIS_UPDATE", (data) => {
6665
7038
  const event = data;
6666
7039
  let previous = null;
@@ -6757,6 +7130,8 @@ class Client extends EventEmitter2 {
6757
7130
  this.emit("autoModerationRuleDelete" /* AutoModerationRuleDelete */, rule);
6758
7131
  });
6759
7132
  this.#gateway.on("AUTO_MODERATION_ACTION_EXECUTION", (data) => this.emit("autoModerationActionExecution" /* AutoModerationActionExecution */, data));
7133
+ }
7134
+ #wireChannels() {
6760
7135
  this.#gateway.on("CHANNEL_CREATE", (data) => {
6761
7136
  const channel = this.channels.upsert(data);
6762
7137
  this.emit("channelCreate" /* ChannelCreate */, channel);
@@ -6824,6 +7199,8 @@ class Client extends EventEmitter2 {
6824
7199
  this.emit("inviteDelete" /* InviteDelete */, invite);
6825
7200
  });
6826
7201
  this.#gateway.on("WEBHOOKS_UPDATE", (data) => this.emit("webhooksUpdate" /* WebhooksUpdate */, data));
7202
+ }
7203
+ #wireMisc() {
6827
7204
  this.#gateway.on("VOICE_STATE_UPDATE", (data) => {
6828
7205
  const state = data;
6829
7206
  if (state.guild_id)
@@ -6899,7 +7276,7 @@ class Client extends EventEmitter2 {
6899
7276
  get resourceContext() {
6900
7277
  return this.#resourceContext;
6901
7278
  }
6902
- #memberPermissions(guildId, memberId, roleIds, channelId) {
7279
+ #memberPermissions(guildId, memberId, roleIds, channelId, timedOutUntil) {
6903
7280
  const guild = this.guilds.get(guildId);
6904
7281
  if (!guild)
6905
7282
  return null;
@@ -6916,7 +7293,8 @@ class Client extends EventEmitter2 {
6916
7293
  memberId,
6917
7294
  memberRoleIds: [...roleIds],
6918
7295
  roles: this.guilds.roles(guildId).values(),
6919
- overwrites: channel?.permissionOverwrites
7296
+ overwrites: channel?.permissionOverwrites,
7297
+ timedOutUntil
6920
7298
  });
6921
7299
  }
6922
7300
  permissionsFor(memberId, guildOrChannelId) {
@@ -6937,7 +7315,8 @@ class Client extends EventEmitter2 {
6937
7315
  memberId,
6938
7316
  memberRoleIds: member.roleIds,
6939
7317
  roles: this.guilds.roles(guildId).values(),
6940
- overwrites: channel?.permissionOverwrites
7318
+ overwrites: channel?.permissionOverwrites,
7319
+ timedOutUntil: member.timedOutUntil
6941
7320
  });
6942
7321
  }
6943
7322
  fetchDefaultSoundboardSounds() {
@@ -6985,10 +7364,10 @@ class Client extends EventEmitter2 {
6985
7364
  return Promise.reject(new Error("Client is unauthenticated."));
6986
7365
  return this.rest.delete(Routes.interactionOriginalResponse(this.user.id, token));
6987
7366
  }
6988
- followUpInteraction(token, data) {
7367
+ async followUpInteraction(token, data) {
6989
7368
  if (!this.user)
6990
7369
  return Promise.reject(new Error("Client is unauthenticated."));
6991
- return this.rest.post(`/webhooks/${this.user.id}/${token}`, toRequest(data, this.options.allowedMentions));
7370
+ return this.rest.post(Routes.webhook(this.user.id, token), toRequest(data, this.options.allowedMentions));
6992
7371
  }
6993
7372
  interactionWebhookMessage(method, applicationId, token, messageId, data) {
6994
7373
  const path = messageId === "@original" ? Routes.interactionOriginalResponse(applicationId, token) : Routes.webhookMessage(applicationId, token, messageId);
@@ -6998,11 +7377,11 @@ class Client extends EventEmitter2 {
6998
7377
  return this.rest.patch(path, data ? toRequest(data, this.options.allowedMentions) : data);
6999
7378
  return this.rest.delete(path);
7000
7379
  }
7001
- fetchWebhook(id, token) {
7002
- return this.rest.get(token ? `/webhooks/${id}/${token}` : `/webhooks/${id}`);
7380
+ async fetchWebhook(id, token) {
7381
+ return this.rest.get(Routes.webhook(id, token));
7003
7382
  }
7004
- fetchGuildPreview(guildId) {
7005
- return this.rest.get(`/guilds/${guildId}/preview`);
7383
+ async fetchGuildPreview(guildId) {
7384
+ return this.rest.get(Routes.guildPreview(guildId));
7006
7385
  }
7007
7386
  fetchVoiceRegions() {
7008
7387
  return this.rest.get("/voice/regions");
@@ -7011,15 +7390,13 @@ class Client extends EventEmitter2 {
7011
7390
  const query = new URLSearchParams;
7012
7391
  if (options?.withCounts)
7013
7392
  query.set("with_counts", "true");
7014
- if (options?.withExpiration)
7015
- query.set("with_expiration", "true");
7016
7393
  if (options?.guildScheduledEventId)
7017
7394
  query.set("guild_scheduled_event_id", options.guildScheduledEventId);
7018
7395
  const qs = query.toString();
7019
7396
  return this.rest.get(`/invites/${encodeURIComponent(code)}${qs ? `?${qs}` : ""}`);
7020
7397
  }
7021
- fetchSticker(id) {
7022
- return this.rest.get(`/stickers/${id}`);
7398
+ async fetchSticker(id) {
7399
+ return this.rest.get(Routes.sticker(id));
7023
7400
  }
7024
7401
  fetchPremiumStickerPacks() {
7025
7402
  return this.rest.get(`/sticker-packs`);
@@ -7079,13 +7456,17 @@ function inlineCode(text) {
7079
7456
  return `\`${text}\``;
7080
7457
  }
7081
7458
  function codeBlock(text, language = "") {
7082
- return `\`\`\`${language}
7083
- ${text}
7459
+ const safe = text.replace(/```/g, "`\u200B``");
7460
+ const lang = language.replace(/[^\w+#.-]/g, "");
7461
+ return `\`\`\`${lang}
7462
+ ${safe}
7084
7463
  \`\`\``;
7085
7464
  }
7086
7465
  function link(label, url, title) {
7087
- const titlePart = title ? ` "${title}"` : "";
7088
- return `[${label}](${url}${titlePart})`;
7466
+ const text = label.replace(/[[\]\\]/g, "\\$&").replace(/\n/g, " ");
7467
+ const target = url.replace(/[()\s"]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`);
7468
+ const titlePart = title ? ` "${title.replace(/["\n]/g, "")}"` : "";
7469
+ return `[${text}](${target}${titlePart})`;
7089
7470
  }
7090
7471
  function blockQuote(text) {
7091
7472
  return text.split(`
@@ -7124,14 +7505,9 @@ function validateSnowflake(id, field) {
7124
7505
  }
7125
7506
  // packages/handlers/src/index.ts
7126
7507
  class HandlerRegistry {
7127
- #handlers = new Map;
7508
+ #handlers = {};
7128
7509
  on(event, handler) {
7129
- let handlers = this.#handlers.get(event);
7130
- if (!handlers) {
7131
- handlers = new Set;
7132
- this.#handlers.set(event, handlers);
7133
- }
7134
- handlers.add(handler);
7510
+ (this.#handlers[event] ??= new Set).add(handler);
7135
7511
  return this;
7136
7512
  }
7137
7513
  once(event, handler) {
@@ -7142,11 +7518,11 @@ class HandlerRegistry {
7142
7518
  return this.on(event, wrapped);
7143
7519
  }
7144
7520
  off(event, handler) {
7145
- this.#handlers.get(event)?.delete(handler);
7521
+ this.#handlers[event]?.delete(handler);
7146
7522
  return this;
7147
7523
  }
7148
7524
  async dispatch(event, ...args) {
7149
- for (const handler of this.#handlers.get(event) ?? [])
7525
+ for (const handler of this.#handlers[event] ?? [])
7150
7526
  await handler(...args);
7151
7527
  }
7152
7528
  emit(event, ...args) {
@@ -7156,7 +7532,7 @@ class HandlerRegistry {
7156
7532
  // packages/sharding/package.json
7157
7533
  var package_default2 = {
7158
7534
  name: "@lunibee/sharding",
7159
- version: "0.2.2",
7535
+ version: "0.2.4",
7160
7536
  type: "module",
7161
7537
  module: "./src/index.ts",
7162
7538
  types: "./src/index.ts",
@@ -7369,12 +7745,12 @@ class ClusterManager {
7369
7745
  const clusterCount = this.#options.clusterCount ?? cpus().length;
7370
7746
  const chunks = Array.from({ length: clusterCount }, () => []);
7371
7747
  for (let i = 0;i < count; i++) {
7372
- chunks[i % clusterCount].push(i);
7748
+ chunks[i % clusterCount]?.push(i);
7373
7749
  }
7374
- for (let i = 0;i < clusterCount; i++) {
7375
- if (chunks[i].length === 0)
7750
+ for (const [i, chunk] of chunks.entries()) {
7751
+ if (chunk.length === 0)
7376
7752
  continue;
7377
- this.#launch(i, chunks[i], count);
7753
+ this.#launch(i, chunk, count);
7378
7754
  await sleep2(500);
7379
7755
  }
7380
7756
  if (this.#options.autoScaleInterval && this.#options.autoScaleInterval > 0) {
@@ -7901,6 +8277,9 @@ var SpeakingFlags = {
7901
8277
  Soundshare: 2,
7902
8278
  Priority: 4
7903
8279
  };
8280
+ function listenerSet(sets, event) {
8281
+ return sets[event] ??= new Set;
8282
+ }
7904
8283
 
7905
8284
  class VoiceConnection {
7906
8285
  state = "disconnected" /* Disconnected */;
@@ -7910,7 +8289,7 @@ class VoiceConnection {
7910
8289
  selfDeaf;
7911
8290
  gateway;
7912
8291
  udp;
7913
- #listeners = new Map;
8292
+ #listeners = {};
7914
8293
  receiver;
7915
8294
  constructor(options) {
7916
8295
  const resolved = typeof options === "string" ? { guildId: options } : options;
@@ -7926,14 +8305,11 @@ class VoiceConnection {
7926
8305
  on(event, listener) {
7927
8306
  if (typeof listener !== "function")
7928
8307
  throw new TypeError("Voice listener must be a function.");
7929
- let listeners = this.#listeners.get(event);
7930
- if (!listeners)
7931
- this.#listeners.set(event, listeners = new Set);
7932
- listeners.add(listener);
8308
+ listenerSet(this.#listeners, event).add(listener);
7933
8309
  return this;
7934
8310
  }
7935
8311
  off(event, listener) {
7936
- this.#listeners.get(event)?.delete(listener);
8312
+ this.#listeners[event]?.delete(listener);
7937
8313
  return this;
7938
8314
  }
7939
8315
  attachTransports(gateway, udp) {
@@ -7976,7 +8352,7 @@ class VoiceConnection {
7976
8352
  this.receiver.close();
7977
8353
  this.channelId = undefined;
7978
8354
  this.#transition("destroyed" /* Destroyed */);
7979
- this.#listeners.clear();
8355
+ this.#listeners = {};
7980
8356
  }
7981
8357
  setChannel(channelId) {
7982
8358
  this.assertUsable();
@@ -8027,7 +8403,7 @@ class VoiceConnection {
8027
8403
  this.state = next;
8028
8404
  if (previous === next)
8029
8405
  return;
8030
- for (const listener of this.#listeners.get("stateChange") ?? []) {
8406
+ for (const listener of this.#listeners.stateChange ?? []) {
8031
8407
  try {
8032
8408
  listener(next, previous);
8033
8409
  } catch (error) {
@@ -8040,7 +8416,7 @@ class VoiceConnection {
8040
8416
  }
8041
8417
  }
8042
8418
  #emit(event, ...args) {
8043
- for (const listener of this.#listeners.get(event) ?? []) {
8419
+ for (const listener of this.#listeners[event] ?? []) {
8044
8420
  try {
8045
8421
  listener(...args);
8046
8422
  } catch {}
@@ -8067,7 +8443,7 @@ class AudioPlayer {
8067
8443
  #stream;
8068
8444
  #reader;
8069
8445
  #resumeSignal;
8070
- #listeners = new Map;
8446
+ #playerListeners = {};
8071
8447
  get state() {
8072
8448
  return this.#state;
8073
8449
  }
@@ -8112,15 +8488,11 @@ class AudioPlayer {
8112
8488
  }
8113
8489
  }
8114
8490
  on(event, listener) {
8115
- let set = this.#listeners.get(event);
8116
- if (!set) {
8117
- this.#listeners.set(event, set = new Set);
8118
- }
8119
- set.add(listener);
8491
+ listenerSet(this.#playerListeners, event).add(listener);
8120
8492
  return this;
8121
8493
  }
8122
8494
  off(event, listener) {
8123
- this.#listeners.get(event)?.delete(listener);
8495
+ this.#playerListeners[event]?.delete(listener);
8124
8496
  return this;
8125
8497
  }
8126
8498
  onChunk(chunk) {}
@@ -8162,7 +8534,7 @@ class AudioPlayer {
8162
8534
  this.#emit("error", err instanceof Error ? err : new VoiceError(String(err)));
8163
8535
  }
8164
8536
  #emit(event, ...args) {
8165
- for (const listener of this.#listeners.get(event) ?? []) {
8537
+ for (const listener of this.#playerListeners[event] ?? []) {
8166
8538
  try {
8167
8539
  listener(...args);
8168
8540
  } catch {}
@@ -8224,9 +8596,10 @@ class VoiceReceiver {
8224
8596
  const controllers = this.#streams.get(userId);
8225
8597
  if (!controllers || controllers.size === 0)
8226
8598
  return;
8227
- const csrcCount = packet[0] & 15;
8599
+ const first = view.getUint8(0);
8600
+ const csrcCount = first & 15;
8228
8601
  let offset = 12 + csrcCount * 4;
8229
- const hasExtension = (packet[0] & 16) !== 0;
8602
+ const hasExtension = (first & 16) !== 0;
8230
8603
  if (hasExtension) {
8231
8604
  if (packet.length < offset + 4)
8232
8605
  return;
@@ -8423,24 +8796,6 @@ function url(value, field) {
8423
8796
  }
8424
8797
  var EmbedBuilder = CreateEmbed;
8425
8798
  // packages/builders/src/components.ts
8426
- var ComponentEnum = {
8427
- ActionRow: 1,
8428
- Button: 2,
8429
- StringSelect: 3,
8430
- TextInput: 4,
8431
- UserSelect: 5,
8432
- RoleSelect: 6,
8433
- MentionableSelect: 7,
8434
- ChannelSelect: 8,
8435
- Section: 9,
8436
- TextDisplay: 10,
8437
- Thumbnail: 11,
8438
- MediaGallery: 12,
8439
- File: 13,
8440
- Separator: 14,
8441
- ContentInventoryEntry: 16,
8442
- Container: 17
8443
- };
8444
8799
  var TextInputType = { Short: 1, Paragraph: 2 };
8445
8800
 
8446
8801
  class CreateActionRow {
@@ -8468,38 +8823,50 @@ class CreateActionRow {
8468
8823
  }
8469
8824
  }
8470
8825
 
8471
- class CreateStringSelect {
8472
- #data = {
8473
- type: ComponentEnum.StringSelect
8474
- };
8826
+ class CreateSelectMenu {
8827
+ #select;
8828
+ constructor(data) {
8829
+ this.#select = data;
8830
+ }
8475
8831
  setCustomId(value) {
8476
8832
  validateText(value, 100, "Component custom ID");
8477
- this.#data.custom_id = value;
8833
+ this.#select.custom_id = value;
8478
8834
  return this;
8479
8835
  }
8480
8836
  setPlaceholder(value) {
8481
8837
  validateText(value, 150, "Component placeholder");
8482
- this.#data.placeholder = value;
8838
+ this.#select.placeholder = value;
8483
8839
  return this;
8484
8840
  }
8485
8841
  setMinValues(value) {
8486
8842
  validateCount(value, "min_values", 0);
8487
- this.#data.min_values = value;
8843
+ this.#select.min_values = value;
8488
8844
  return this;
8489
8845
  }
8490
8846
  setMaxValues(value) {
8491
8847
  validateCount(value, "max_values", 1);
8492
- this.#data.max_values = value;
8848
+ this.#select.max_values = value;
8493
8849
  return this;
8494
8850
  }
8495
8851
  setRequired(value = true) {
8496
- this.#data.required = value;
8852
+ this.#select.required = value;
8497
8853
  return this;
8498
8854
  }
8499
8855
  setDisabled(value = true) {
8500
- this.#data.disabled = value;
8856
+ this.#select.disabled = value;
8501
8857
  return this;
8502
8858
  }
8859
+ }
8860
+
8861
+ class CreateStringSelect extends CreateSelectMenu {
8862
+ #data;
8863
+ constructor() {
8864
+ const data = {
8865
+ type: ComponentEnum.StringSelect
8866
+ };
8867
+ super(data);
8868
+ this.#data = data;
8869
+ }
8503
8870
  addOptions(...options) {
8504
8871
  if (!options.length)
8505
8872
  throw new TypeError("At least one select option is required.");
@@ -8615,40 +8982,14 @@ class CreateButton {
8615
8982
  }
8616
8983
  }
8617
8984
 
8618
- class CreateEntitySelect {
8985
+ class CreateEntitySelect extends CreateSelectMenu {
8619
8986
  #data;
8620
8987
  constructor(type) {
8621
8988
  if (type !== ComponentEnum.UserSelect && type !== ComponentEnum.RoleSelect && type !== ComponentEnum.MentionableSelect && type !== ComponentEnum.ChannelSelect)
8622
8989
  throw new TypeError("Invalid select component type.");
8623
- this.#data = { type };
8624
- }
8625
- setCustomId(value) {
8626
- validateText(value, 100, "Component custom ID");
8627
- this.#data.custom_id = value;
8628
- return this;
8629
- }
8630
- setPlaceholder(value) {
8631
- validateText(value, 150, "Component placeholder");
8632
- this.#data.placeholder = value;
8633
- return this;
8634
- }
8635
- setMinValues(value) {
8636
- validateCount(value, "min_values", 0);
8637
- this.#data.min_values = value;
8638
- return this;
8639
- }
8640
- setMaxValues(value) {
8641
- validateCount(value, "max_values", 1);
8642
- this.#data.max_values = value;
8643
- return this;
8644
- }
8645
- setRequired(value = true) {
8646
- this.#data.required = value;
8647
- return this;
8648
- }
8649
- setDisabled(value = true) {
8650
- this.#data.disabled = value;
8651
- return this;
8990
+ const data = { type };
8991
+ super(data);
8992
+ this.#data = data;
8652
8993
  }
8653
8994
  setDefaultValues(...values) {
8654
8995
  this.#data.default_values = values.map((value) => ({ ...value }));
@@ -9028,6 +9369,10 @@ var ApplicationCommandOptionEnum2 = {
9028
9369
  Number: 10,
9029
9370
  Attachment: 11
9030
9371
  };
9372
+ function validateContexts(contexts) {
9373
+ if (contexts.some((context) => context !== 0 && context !== 1 && context !== 2))
9374
+ throw new RangeError("Command contexts must be 0, 1 or 2.");
9375
+ }
9031
9376
 
9032
9377
  class CreateSlashCommand {
9033
9378
  #data = { type: 1 };
@@ -9041,6 +9386,11 @@ class CreateSlashCommand {
9041
9386
  this.#data.description = description;
9042
9387
  return this;
9043
9388
  }
9389
+ setContexts(...contexts) {
9390
+ validateContexts(contexts);
9391
+ this.#data.contexts = [...contexts];
9392
+ return this;
9393
+ }
9044
9394
  setDMPermission(enabled) {
9045
9395
  this.#data.dm_permission = enabled;
9046
9396
  return this;
@@ -9097,16 +9447,7 @@ class CreateSlashCommand {
9097
9447
  return structuredClone(this.#data);
9098
9448
  }
9099
9449
  addOption(option) {
9100
- const options = this.#data.options ?? [];
9101
- if (options.length >= 25)
9102
- throw new RangeError("An application command cannot contain more than 25 options.");
9103
- const payload = option.toJSON();
9104
- if (options.some((existing) => existing.name === payload.name))
9105
- throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
9106
- if (payload.required === true && options.some((existing) => existing.required !== true))
9107
- throw new RangeError("Required application command options must be placed before optional options.");
9108
- options.push(payload);
9109
- this.#data.options = options;
9450
+ this.#data.options = appendOption(this.#data.options, option.toJSON(), "application command");
9110
9451
  return this;
9111
9452
  }
9112
9453
  }
@@ -9144,21 +9485,9 @@ class CreateStringOption extends CreateCommandOption {
9144
9485
  super(ApplicationCommandOptionEnum2.String);
9145
9486
  }
9146
9487
  addChoices(...choices) {
9147
- const current = this.data.choices ?? [];
9148
- if (!choices.length)
9149
- throw new TypeError("At least one choice is required.");
9150
- if (this.data.autocomplete === true)
9151
- throw new RangeError("Autocomplete options cannot define choices.");
9152
- if (current.length + choices.length > 25)
9153
- throw new RangeError("An option cannot contain more than 25 choices.");
9154
- for (const choice of choices) {
9155
- validateText2(choice.name, "Choice name", 100);
9488
+ for (const choice of choices)
9156
9489
  validateText2(choice.value, "Choice value", 100);
9157
- }
9158
- this.data.choices = [
9159
- ...current,
9160
- ...choices.map((choice) => ({ ...choice }))
9161
- ];
9490
+ appendChoices(this.data, choices);
9162
9491
  return this;
9163
9492
  }
9164
9493
  setMinLength(value) {
@@ -9175,18 +9504,21 @@ class CreateStringOption extends CreateCommandOption {
9175
9504
  }
9176
9505
  }
9177
9506
 
9178
- class CreateIntegerOption extends CreateCommandOption {
9179
- constructor() {
9180
- super(ApplicationCommandOptionEnum2.Integer);
9507
+ class CreateNumericOption extends CreateCommandOption {
9508
+ #integer;
9509
+ constructor(type, integer) {
9510
+ super(type);
9511
+ this.#integer = integer;
9181
9512
  }
9182
9513
  setMinValue(value) {
9183
- validateNumberRange(value, -9007199254740991, 9007199254740991, "min_value", true);
9514
+ validateNumberRange(value, -MAX_SAFE, MAX_SAFE, "min_value", this.#integer);
9184
9515
  this.data.min_value = value;
9185
9516
  return this;
9186
9517
  }
9187
9518
  setMaxValue(value) {
9188
- validateNumberRange(value, -9007199254740991, 9007199254740991, "max_value", true);
9189
- if (this.data.min_value !== undefined && this.data.min_value > value)
9519
+ validateNumberRange(value, -MAX_SAFE, MAX_SAFE, "max_value", this.#integer);
9520
+ const min = this.data.min_value;
9521
+ if (min !== undefined && min > value)
9190
9522
  throw new RangeError("min_value cannot exceed max_value.");
9191
9523
  this.data.max_value = value;
9192
9524
  return this;
@@ -9198,50 +9530,20 @@ class CreateIntegerOption extends CreateCommandOption {
9198
9530
  return this;
9199
9531
  }
9200
9532
  addChoices(...choices) {
9201
- const current = this.data.choices ?? [];
9202
- if (!choices.length)
9203
- throw new TypeError("At least one choice is required.");
9204
- if (this.data.autocomplete === true)
9205
- throw new RangeError("Autocomplete options cannot define choices.");
9206
- if (current.length + choices.length > 25)
9207
- throw new RangeError("An option cannot contain more than 25 choices.");
9208
- this.data.choices = [...current, ...choices];
9533
+ appendChoices(this.data, choices);
9209
9534
  return this;
9210
9535
  }
9211
9536
  }
9212
9537
 
9213
- class CreateNumberOption extends CreateCommandOption {
9538
+ class CreateIntegerOption extends CreateNumericOption {
9214
9539
  constructor() {
9215
- super(ApplicationCommandOptionEnum2.Number);
9540
+ super(ApplicationCommandOptionEnum2.Integer, true);
9216
9541
  }
9217
- setMinValue(value) {
9218
- validateNumberRange(value, -9007199254740991, 9007199254740991, "min_value", false);
9219
- this.data.min_value = value;
9220
- return this;
9221
- }
9222
- setMaxValue(value) {
9223
- validateNumberRange(value, -9007199254740991, 9007199254740991, "max_value", false);
9224
- if (this.data.min_value !== undefined && this.data.min_value > value)
9225
- throw new RangeError("min_value cannot exceed max_value.");
9226
- this.data.max_value = value;
9227
- return this;
9228
- }
9229
- setAutocomplete(enabled = true) {
9230
- if (enabled && Array.isArray(this.data.choices) && this.data.choices.length)
9231
- throw new RangeError("Autocomplete options cannot define choices.");
9232
- this.data.autocomplete = enabled;
9233
- return this;
9234
- }
9235
- addChoices(...choices) {
9236
- const current = this.data.choices ?? [];
9237
- if (!choices.length)
9238
- throw new TypeError("At least one choice is required.");
9239
- if (this.data.autocomplete === true)
9240
- throw new RangeError("Autocomplete options cannot define choices.");
9241
- if (current.length + choices.length > 25)
9242
- throw new RangeError("An option cannot contain more than 25 choices.");
9243
- this.data.choices = [...current, ...choices];
9244
- return this;
9542
+ }
9543
+
9544
+ class CreateNumberOption extends CreateNumericOption {
9545
+ constructor() {
9546
+ super(ApplicationCommandOptionEnum2.Number, false);
9245
9547
  }
9246
9548
  }
9247
9549
 
@@ -9320,17 +9622,9 @@ class CreateSubcommand extends CreateCommandOption {
9320
9622
  }
9321
9623
  addChildOption(option) {
9322
9624
  const options = this.data.options ?? [];
9323
- if (options.length >= 25)
9324
- throw new RangeError("A subcommand cannot contain more than 25 options.");
9325
- const payload = option.toJSON();
9326
- if (options.some((existing) => existing.name === payload.name))
9327
- throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
9328
- if (payload.required === true && options.some((existing) => existing.required !== true))
9329
- throw new RangeError("Required subcommand options must be placed before optional options.");
9330
9625
  if (options.some((existing) => existing.type === ApplicationCommandOptionEnum2.Subcommand))
9331
9626
  throw new RangeError("Subcommands cannot contain nested subcommands.");
9332
- options.push(payload);
9333
- this.data.options = options;
9627
+ this.data.options = appendOption(options, option.toJSON(), "subcommand");
9334
9628
  return this;
9335
9629
  }
9336
9630
  }
@@ -9353,6 +9647,29 @@ class CreateSubcommandGroup extends CreateCommandOption {
9353
9647
  return this;
9354
9648
  }
9355
9649
  }
9650
+ var MAX_SAFE = Number.MAX_SAFE_INTEGER;
9651
+ function appendOption(options, payload, parent) {
9652
+ const list = options ?? [];
9653
+ if (list.length >= 25)
9654
+ throw new RangeError(`${parent === "subcommand" ? "A subcommand" : "An application command"} cannot contain more than 25 options.`);
9655
+ if (list.some((existing) => existing.name === payload.name))
9656
+ throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
9657
+ if (payload.required === true && list.some((existing) => existing.required !== true))
9658
+ throw new RangeError(`Required ${parent} options must be placed before optional options.`);
9659
+ return [...list, payload];
9660
+ }
9661
+ function appendChoices(data, choices) {
9662
+ const current = data.choices ?? [];
9663
+ if (!choices.length)
9664
+ throw new TypeError("At least one choice is required.");
9665
+ if (data.autocomplete === true)
9666
+ throw new RangeError("Autocomplete options cannot define choices.");
9667
+ if (current.length + choices.length > 25)
9668
+ throw new RangeError("An option cannot contain more than 25 choices.");
9669
+ for (const choice of choices)
9670
+ validateText2(choice.name, "Choice name", 100);
9671
+ data.choices = [...current, ...choices.map((choice) => ({ ...choice }))];
9672
+ }
9356
9673
  function validateName(value, field) {
9357
9674
  if (!/^[\p{L}\p{N}_-]{1,32}$/u.test(value) || value !== value.toLowerCase())
9358
9675
  throw new RangeError(`${field} must contain 1-32 lowercase letters, numbers, underscores, or hyphens.`);
@@ -9400,8 +9717,7 @@ class CreateContextMenuCommand {
9400
9717
  return this;
9401
9718
  }
9402
9719
  setContexts(...contexts) {
9403
- if (contexts.some((context) => context !== 0 && context !== 1 && context !== 2))
9404
- throw new RangeError("Command contexts must be 0, 1 or 2.");
9720
+ validateContexts(contexts);
9405
9721
  this.data.contexts = [...contexts];
9406
9722
  return this;
9407
9723
  }
@@ -9442,13 +9758,14 @@ var SubcommandGroupBuilder = CreateSubcommandGroup;
9442
9758
  var UserCommandBuilder = CreateUserCommand;
9443
9759
  var UserOptionBuilder = CreateUserOption;
9444
9760
  // packages/builders/src/attachment.ts
9445
- import { readFile } from "fs/promises";
9446
- import { basename } from "path";
9761
+ import { readFile, realpath } from "fs/promises";
9762
+ import { basename, isAbsolute, relative, resolve } from "path";
9447
9763
 
9448
9764
  class CreateAttachment {
9449
9765
  name;
9450
9766
  description;
9451
9767
  file;
9768
+ root;
9452
9769
  constructor(file, data) {
9453
9770
  this.file = file;
9454
9771
  if (typeof data === "string") {
@@ -9456,6 +9773,7 @@ class CreateAttachment {
9456
9773
  } else {
9457
9774
  this.name = data?.name ?? (typeof file === "string" ? basename(file) : "file.bin");
9458
9775
  this.description = data?.description;
9776
+ this.root = data?.root;
9459
9777
  }
9460
9778
  }
9461
9779
  setName(name) {
@@ -9472,7 +9790,8 @@ class CreateAttachment {
9472
9790
  }
9473
9791
  async toBuffer() {
9474
9792
  if (typeof this.file === "string") {
9475
- const buffer = await readFile(this.file);
9793
+ const path = this.root === undefined ? this.file : await insideRoot(this.root, this.file);
9794
+ const buffer = await readFile(path);
9476
9795
  return new Uint8Array(buffer);
9477
9796
  }
9478
9797
  if (this.file instanceof Uint8Array)
@@ -9490,6 +9809,16 @@ class CreateAttachment {
9490
9809
  }
9491
9810
  }
9492
9811
  var AttachmentBuilder = CreateAttachment;
9812
+ async function insideRoot(root, file) {
9813
+ const base = await realpath(root);
9814
+ const target = await realpath(resolve(base, file)).catch(() => {
9815
+ throw new Error("Attachment file was not found inside its root.");
9816
+ });
9817
+ const rel = relative(base, target);
9818
+ if (rel === "" || rel.startsWith("..") || isAbsolute(rel))
9819
+ throw new Error("Attachment file is outside its root folder.");
9820
+ return target;
9821
+ }
9493
9822
  export {
9494
9823
  ActionRowBuilder,
9495
9824
  ActivityEnum,
@@ -9544,6 +9873,7 @@ export {
9544
9873
  CreateButton,
9545
9874
  CreateChannelOption,
9546
9875
  CreateChannelSelectMenu,
9876
+ CreateCommandOption,
9547
9877
  CreateContainer,
9548
9878
  CreateContentInventoryEntry,
9549
9879
  CreateContextMenuCommand,
@@ -9646,6 +9976,7 @@ export {
9646
9976
  PremiumTier,
9647
9977
  REST,
9648
9978
  RESTError,
9979
+ RESTErrorCode,
9649
9980
  RateLimiter,
9650
9981
  RedisRateLimitStore,
9651
9982
  RequestScheduler,
@@ -9761,4 +10092,4 @@ export {
9761
10092
  userMention
9762
10093
  };
9763
10094
 
9764
- //# debugId=FC58C0F70BD3B2A964756E2164756E21
10095
+ //# debugId=4ECD86428171907F64756E2164756E21