lunibee 0.1.8 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +2 -0
  2. package/dist/builders/components.d.ts +30 -2
  3. package/dist/builders/embed.d.ts +7 -7
  4. package/dist/builders/index.d.ts +1 -1
  5. package/dist/builders/index.js +110 -18
  6. package/dist/builders/index.js.map +6 -6
  7. package/dist/collection/index.d.ts +68 -1
  8. package/dist/collection/index.js +334 -1
  9. package/dist/collection/index.js.map +3 -3
  10. package/dist/core/collector.d.ts +13 -0
  11. package/dist/core/events.d.ts +29 -3
  12. package/dist/core/index.d.ts +25 -9
  13. package/dist/core/index.js +1745 -134
  14. package/dist/core/index.js.map +30 -26
  15. package/dist/core/permissions.d.ts +48 -0
  16. package/dist/index.js +2102 -362
  17. package/dist/index.js.map +36 -34
  18. package/dist/managers/advanced.d.ts +116 -0
  19. package/dist/managers/base.d.ts +13 -2
  20. package/dist/managers/emoji.d.ts +1 -1
  21. package/dist/managers/guild-resources.d.ts +22 -2
  22. package/dist/managers/guild.d.ts +31 -3
  23. package/dist/managers/index.d.ts +38 -6
  24. package/dist/managers/index.js +996 -160
  25. package/dist/managers/index.js.map +20 -18
  26. package/dist/managers/member.d.ts +13 -12
  27. package/dist/managers/message.d.ts +21 -4
  28. package/dist/rest/errors.d.ts +33 -0
  29. package/dist/rest/index.d.ts +1 -1
  30. package/dist/rest/index.js +52 -6
  31. package/dist/rest/index.js.map +5 -5
  32. package/dist/rest/routes.d.ts +20 -0
  33. package/dist/sharding/index.d.ts +29 -0
  34. package/dist/sharding/index.js +99 -15
  35. package/dist/sharding/index.js.map +8 -8
  36. package/dist/structures/base.d.ts +38 -0
  37. package/dist/structures/index.d.ts +29 -0
  38. package/dist/structures/index.js +208 -46
  39. package/dist/structures/index.js.map +13 -12
  40. package/dist/structures/interactions.d.ts +51 -1
  41. package/dist/structures/options.d.ts +2 -0
  42. package/dist/structures/resources.d.ts +29 -3
  43. package/dist/types/gateway.d.ts +16 -0
  44. package/dist/types/index.d.ts +67 -1
  45. package/dist/types/index.js.map +3 -3
  46. package/dist/utils/args.d.ts +79 -0
  47. package/dist/utils/index.d.ts +1 -0
  48. package/dist/utils/index.js +190 -2
  49. package/dist/utils/index.js.map +5 -4
  50. package/dist/voice/index.d.ts +3 -0
  51. package/dist/voice/index.js +15 -1
  52. package/dist/voice/index.js.map +3 -3
  53. package/dist/ws/index.js +13 -5
  54. package/dist/ws/index.js.map +6 -6
  55. package/package.json +14 -14
@@ -1,6 +1,339 @@
1
1
  // @bun
2
2
  // packages/collection/src/index.ts
3
+ class RecencyList {
4
+ #nodes = new Map;
5
+ #oldest;
6
+ #newest;
7
+ get size() {
8
+ return this.#nodes.size;
9
+ }
10
+ oldest() {
11
+ return this.#oldest?.key;
12
+ }
13
+ touch(key) {
14
+ const node = this.#nodes.get(key);
15
+ if (node)
16
+ return this.#moveNewest(node);
17
+ const created = { key, older: this.#newest };
18
+ if (this.#newest)
19
+ this.#newest.newer = created;
20
+ else
21
+ this.#oldest = created;
22
+ this.#newest = created;
23
+ this.#nodes.set(key, created);
24
+ }
25
+ promote(key) {
26
+ const node = this.#nodes.get(key);
27
+ if (node)
28
+ this.#moveNewest(node);
29
+ }
30
+ delete(key) {
31
+ const node = this.#nodes.get(key);
32
+ if (!node)
33
+ return false;
34
+ this.#unlink(node);
35
+ this.#nodes.delete(key);
36
+ return true;
37
+ }
38
+ clear() {
39
+ this.#nodes.clear();
40
+ this.#oldest = this.#newest = undefined;
41
+ }
42
+ #unlink(node) {
43
+ if (node.older)
44
+ node.older.newer = node.newer;
45
+ else
46
+ this.#oldest = node.newer;
47
+ if (node.newer)
48
+ node.newer.older = node.older;
49
+ else
50
+ this.#newest = node.older;
51
+ node.older = node.newer = undefined;
52
+ }
53
+ #moveNewest(node) {
54
+ if (node === this.#newest)
55
+ return;
56
+ this.#unlink(node);
57
+ node.older = this.#newest;
58
+ if (this.#newest)
59
+ this.#newest.newer = node;
60
+ else
61
+ this.#oldest = node;
62
+ this.#newest = node;
63
+ }
64
+ }
65
+ function assertTTL(ttl) {
66
+ if (ttl !== undefined && (!Number.isFinite(ttl) || ttl <= 0))
67
+ throw new RangeError("TTL must be a positive number, or omitted.");
68
+ }
69
+
3
70
  class Collection extends Map {
71
+ #ttl;
72
+ #maxSize;
73
+ #onEvict;
74
+ #expiry = new Map;
75
+ #lru = new RecencyList;
76
+ #stats = {
77
+ hits: 0,
78
+ misses: 0,
79
+ expired: 0,
80
+ evicted: 0
81
+ };
82
+ #heap = [];
83
+ #timer;
84
+ #armedFor = Infinity;
85
+ constructor(entries, options = {}) {
86
+ super();
87
+ assertTTL(options.ttl);
88
+ if (options.maxSize !== undefined && (!Number.isInteger(options.maxSize) || options.maxSize <= 0))
89
+ throw new RangeError("maxSize must be a positive integer.");
90
+ this.#ttl = options.ttl;
91
+ this.#maxSize = options.maxSize;
92
+ this.#onEvict = options.onEvict;
93
+ if (entries)
94
+ for (const [key, value] of entries)
95
+ this.set(key, value);
96
+ }
97
+ set(key, value, ttl) {
98
+ assertTTL(ttl);
99
+ const window = ttl ?? this.#ttl;
100
+ if (this.#maxSize !== undefined) {
101
+ this.#lru.touch(key);
102
+ }
103
+ super.set(key, value);
104
+ if (window !== undefined)
105
+ this.#schedule(key, window);
106
+ else if (this.#expiry.size > 0)
107
+ this.#expiry.delete(key);
108
+ this.#enforceCap();
109
+ return this;
110
+ }
111
+ setWithoutTTL(key, value) {
112
+ if (this.#expiry.size > 0)
113
+ this.#expiry.delete(key);
114
+ if (this.#lru.size > 0)
115
+ this.#lru.delete(key);
116
+ super.set(key, value);
117
+ return this;
118
+ }
119
+ get(key) {
120
+ if (this.#expireIfDue(key)) {
121
+ this.#stats.misses++;
122
+ return;
123
+ }
124
+ const value = super.get(key);
125
+ if (value === undefined && !super.has(key)) {
126
+ this.#stats.misses++;
127
+ return;
128
+ }
129
+ this.#stats.hits++;
130
+ const expiry = this.#expiry.get(key);
131
+ if (expiry)
132
+ expiry.deadline = Date.now() + expiry.window;
133
+ this.#lru.promote(key);
134
+ return value;
135
+ }
136
+ peek(key) {
137
+ if (!this.#expireIfDue(key) && super.has(key)) {
138
+ this.#stats.hits++;
139
+ return super.get(key);
140
+ }
141
+ this.#stats.misses++;
142
+ return;
143
+ }
144
+ get stats() {
145
+ return { ...this.#stats };
146
+ }
147
+ has(key) {
148
+ return !this.#expireIfDue(key) && super.has(key);
149
+ }
150
+ delete(key) {
151
+ if (this.#expireIfDue(key))
152
+ return false;
153
+ this.#expiry.delete(key);
154
+ this.#lru.delete(key);
155
+ return super.delete(key);
156
+ }
157
+ clear() {
158
+ super.clear();
159
+ this.#expiry.clear();
160
+ this.#lru.clear();
161
+ this.#heap.length = 0;
162
+ if (this.#timer)
163
+ clearTimeout(this.#timer);
164
+ this.#timer = undefined;
165
+ this.#armedFor = Infinity;
166
+ }
167
+ get size() {
168
+ this.purge();
169
+ return super.size;
170
+ }
171
+ entries() {
172
+ this.purge();
173
+ return super.entries();
174
+ }
175
+ keys() {
176
+ this.purge();
177
+ return super.keys();
178
+ }
179
+ values() {
180
+ this.purge();
181
+ return super.values();
182
+ }
183
+ [Symbol.iterator]() {
184
+ return this.entries();
185
+ }
186
+ forEach(callback, thisArg) {
187
+ this.purge();
188
+ super.forEach(callback, thisArg);
189
+ }
190
+ ttlRemaining(key) {
191
+ if (this.#expireIfDue(key))
192
+ return;
193
+ const expiry = this.#expiry.get(key);
194
+ return expiry && Math.max(0, expiry.deadline - Date.now());
195
+ }
196
+ purge() {
197
+ if (this.#expiry.size === 0)
198
+ return 0;
199
+ const now = Date.now();
200
+ let removed = 0;
201
+ const dropped = [];
202
+ while (this.#nextDeadline() <= now) {
203
+ const due = this.#heapPop();
204
+ dropped.push([due.key, super.get(due.key)]);
205
+ this.#remove(due.key);
206
+ removed++;
207
+ }
208
+ this.#stats.expired += removed;
209
+ this.#rearm();
210
+ for (const [key, value] of dropped)
211
+ this.#notify(key, value, "expired");
212
+ return removed;
213
+ }
214
+ #expireIfDue(key) {
215
+ const expiry = this.#expiry.get(key);
216
+ if (!expiry || expiry.deadline > Date.now())
217
+ return false;
218
+ const value = super.get(key);
219
+ this.#remove(key);
220
+ this.#stats.expired++;
221
+ this.#notify(key, value, "expired");
222
+ return true;
223
+ }
224
+ #remove(key) {
225
+ this.#expiry.delete(key);
226
+ this.#lru.delete(key);
227
+ super.delete(key);
228
+ }
229
+ #notify(key, value, reason) {
230
+ if (!this.#onEvict)
231
+ return;
232
+ try {
233
+ this.#onEvict(key, value, reason);
234
+ } catch {}
235
+ }
236
+ #enforceCap() {
237
+ if (this.#maxSize === undefined)
238
+ return;
239
+ while (this.#lru.size > this.#maxSize) {
240
+ const oldest = this.#lru.oldest();
241
+ const value = super.get(oldest);
242
+ this.#remove(oldest);
243
+ this.#stats.evicted++;
244
+ this.#notify(oldest, value, "evicted");
245
+ }
246
+ }
247
+ #schedule(key, window) {
248
+ const deadline = Date.now() + window;
249
+ const expiry = this.#expiry.get(key);
250
+ if (expiry) {
251
+ expiry.deadline = deadline;
252
+ expiry.window = window;
253
+ if (deadline >= expiry.filed)
254
+ return;
255
+ expiry.filed = deadline;
256
+ } else
257
+ this.#expiry.set(key, { deadline, window, filed: deadline });
258
+ this.#heapPush({ key, deadline });
259
+ if (this.#heap.length > 2 * this.#expiry.size + 8)
260
+ this.#compact();
261
+ this.#rearm();
262
+ }
263
+ #nextDeadline() {
264
+ for (;; ) {
265
+ const top = this.#heap[0];
266
+ if (top === undefined)
267
+ return Infinity;
268
+ const expiry = this.#expiry.get(top.key);
269
+ if (!expiry || expiry.filed !== top.deadline) {
270
+ this.#heapPop();
271
+ continue;
272
+ }
273
+ if (expiry.deadline === top.deadline)
274
+ return top.deadline;
275
+ this.#heapPop();
276
+ expiry.filed = expiry.deadline;
277
+ this.#heapPush({ key: top.key, deadline: expiry.deadline });
278
+ }
279
+ }
280
+ #compact() {
281
+ const live = this.#heap.filter((record) => this.#expiry.get(record.key)?.filed === record.deadline);
282
+ this.#heap.length = 0;
283
+ for (const record of live)
284
+ this.#heapPush(record);
285
+ }
286
+ #rearm() {
287
+ const deadline = this.#nextDeadline();
288
+ if (this.#timer !== undefined && deadline >= this.#armedFor)
289
+ return;
290
+ if (this.#timer)
291
+ clearTimeout(this.#timer);
292
+ this.#timer = undefined;
293
+ this.#armedFor = deadline;
294
+ if (deadline === Infinity)
295
+ return;
296
+ this.#timer = setTimeout(() => {
297
+ this.#timer = undefined;
298
+ this.#armedFor = Infinity;
299
+ this.purge();
300
+ }, Math.max(0, deadline - Date.now()));
301
+ this.#timer.unref?.();
302
+ }
303
+ #heapPush(record) {
304
+ const heap = this.#heap;
305
+ heap.push(record);
306
+ let i = heap.length - 1;
307
+ while (i > 0) {
308
+ const parent = i - 1 >> 1;
309
+ if (heap[parent].deadline <= heap[i].deadline)
310
+ break;
311
+ [heap[parent], heap[i]] = [heap[i], heap[parent]];
312
+ i = parent;
313
+ }
314
+ }
315
+ #heapPop() {
316
+ const heap = this.#heap;
317
+ const top = heap[0];
318
+ const last = heap.pop();
319
+ if (top === undefined || heap.length === 0)
320
+ return top;
321
+ heap[0] = last;
322
+ for (let i = 0;; ) {
323
+ const left = 2 * i + 1;
324
+ const right = left + 1;
325
+ let smallest = i;
326
+ if (left < heap.length && heap[left].deadline < heap[smallest].deadline)
327
+ smallest = left;
328
+ if (right < heap.length && heap[right].deadline < heap[smallest].deadline)
329
+ smallest = right;
330
+ if (smallest === i)
331
+ break;
332
+ [heap[smallest], heap[i]] = [heap[i], heap[smallest]];
333
+ i = smallest;
334
+ }
335
+ return top;
336
+ }
4
337
  first() {
5
338
  for (const value of this.values())
6
339
  return value;
@@ -225,11 +558,40 @@ class Manager {
225
558
  has(id) {
226
559
  return this.cache.has(id);
227
560
  }
561
+ #inflight = new Map;
562
+ fetchOnce(id, load, store = (value) => {
563
+ this.set(id, value);
564
+ return value;
565
+ }) {
566
+ const pending = this.#inflight.get(id);
567
+ if (pending)
568
+ return pending.promise;
569
+ const entry = {
570
+ promise: new Promise((resolve) => resolve(load())),
571
+ dirty: false
572
+ };
573
+ this.#inflight.set(id, entry);
574
+ entry.promise = entry.promise.then((value) => {
575
+ this.#inflight.delete(id);
576
+ return entry.dirty ? this.get(id) ?? value : store(value);
577
+ }, (error) => {
578
+ this.#inflight.delete(id);
579
+ throw error;
580
+ });
581
+ return entry.promise;
582
+ }
583
+ #markDirty(id) {
584
+ const pending = this.#inflight.get(id);
585
+ if (pending)
586
+ pending.dirty = true;
587
+ }
228
588
  set(id, value) {
229
- this.cache.set(id, value);
589
+ this.#markDirty(id);
590
+ this.cache.setWithoutTTL(id, value);
230
591
  return this;
231
592
  }
232
593
  delete(id) {
594
+ this.#markDirty(id);
233
595
  return this.cache.delete(id);
234
596
  }
235
597
  clear() {
@@ -265,16 +627,20 @@ class ResourceManager extends Manager {
265
627
  async resolve(id) {
266
628
  return this.get(id) ?? this.fetch(id);
267
629
  }
268
- async fetch(id) {
269
- const resource = await this.#fetcher(id);
270
- this.set(id, resource);
271
- return resource;
630
+ fetch(id) {
631
+ return this.fetchOnce(id, () => this.#fetcher(id));
272
632
  }
273
633
  async fetchMany(ids) {
274
634
  return Promise.all([...ids].map((id) => this.resolve(id)));
275
635
  }
276
636
  upsert(resource) {
277
637
  const key = this.#key(resource);
638
+ const existing = this.get(key);
639
+ if (existing !== undefined && existing !== resource && typeof existing === "object" && existing !== null) {
640
+ Object.assign(existing, resource);
641
+ this.set(key, existing);
642
+ return existing;
643
+ }
278
644
  this.set(key, resource);
279
645
  return resource;
280
646
  }
@@ -285,7 +651,7 @@ class ResourceManager extends Manager {
285
651
  // packages/rest/package.json
286
652
  var package_default = {
287
653
  name: "@lunibee/rest",
288
- version: "0.1.8",
654
+ version: "0.2.1",
289
655
  type: "module",
290
656
  module: "./src/index.ts",
291
657
  types: "./src/index.ts",
@@ -352,8 +718,23 @@ var Routes = {
352
718
  invite: (code) => `/invites/${encodeURIComponent(code)}`,
353
719
  guildVanity: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/vanity-url`,
354
720
  guildEmoji: (guildId, emojiId) => emojiId ? `/guilds/${snowflake(guildId, "Guild ID")}/emojis/${snowflake(emojiId, "Emoji ID")}` : `/guilds/${snowflake(guildId, "Guild ID")}/emojis`,
355
- applicationEmoji: (applicationId, emojiId) => emojiId ? `/applications/${snowflake(applicationId, "Application ID")}/emojis/${snowflake(emojiId, "Emoji ID")}` : `/applications/${snowflake(applicationId, "Application ID")}/emojis`
721
+ applicationEmoji: (applicationId, emojiId) => emojiId ? `/applications/${snowflake(applicationId, "Application ID")}/emojis/${snowflake(emojiId, "Emoji ID")}` : `/applications/${snowflake(applicationId, "Application ID")}/emojis`,
722
+ pollExpire: (channelId, messageId) => `/channels/${snowflake(channelId, "Channel ID")}/polls/${snowflake(messageId, "Message ID")}/expire`,
723
+ pollAnswerVoters: (channelId, messageId, answerId) => `/channels/${snowflake(channelId, "Channel ID")}/polls/${snowflake(messageId, "Message ID")}/answers/${integer(answerId, "Answer ID")}`,
724
+ guildSticker: (guildId, stickerId) => stickerId ? `/guilds/${snowflake(guildId, "Guild ID")}/stickers/${snowflake(stickerId, "Sticker ID")}` : `/guilds/${snowflake(guildId, "Guild ID")}/stickers`,
725
+ sendSoundboardSound: (channelId) => `/channels/${snowflake(channelId, "Channel ID")}/send-soundboard-sound`,
726
+ soundboardDefaultSounds: () => "/soundboard-default-sounds",
727
+ guildSoundboardSound: (guildId, soundId) => soundId ? `/guilds/${snowflake(guildId, "Guild ID")}/soundboard-sounds/${snowflake(soundId, "Sound ID")}` : `/guilds/${snowflake(guildId, "Guild ID")}/soundboard-sounds`,
728
+ applicationSkus: (applicationId) => `/applications/${snowflake(applicationId, "Application ID")}/skus`,
729
+ applicationEntitlement: (applicationId, entitlementId) => entitlementId ? `/applications/${snowflake(applicationId, "Application ID")}/entitlements/${snowflake(entitlementId, "Entitlement ID")}` : `/applications/${snowflake(applicationId, "Application ID")}/entitlements`,
730
+ consumeEntitlement: (applicationId, entitlementId) => `/applications/${snowflake(applicationId, "Application ID")}/entitlements/${snowflake(entitlementId, "Entitlement ID")}/consume`,
731
+ skuSubscription: (skuId, subscriptionId) => subscriptionId ? `/skus/${snowflake(skuId, "SKU ID")}/subscriptions/${snowflake(subscriptionId, "Subscription ID")}` : `/skus/${snowflake(skuId, "SKU ID")}/subscriptions`
356
732
  };
733
+ function integer(value, field) {
734
+ if (!Number.isInteger(value) || value < 0)
735
+ throw new TypeError(`${field} must be a non-negative integer.`);
736
+ return String(value);
737
+ }
357
738
  function snowflake(value, field) {
358
739
  if (!/^\d{1,20}$/.test(value))
359
740
  throw new TypeError(`${field} must be a valid Discord snowflake.`);
@@ -446,6 +827,7 @@ class Channel extends BaseStructure {
446
827
  nsfw;
447
828
  rateLimitPerUser;
448
829
  position;
830
+ permissionOverwrites;
449
831
  #context;
450
832
  constructor(data, context) {
451
833
  super(data.id);
@@ -459,6 +841,7 @@ class Channel extends BaseStructure {
459
841
  this.nsfw = data.nsfw;
460
842
  this.rateLimitPerUser = data.rate_limit_per_user;
461
843
  this.position = data.position;
844
+ this.permissionOverwrites = (data.permission_overwrites ?? []).map((overwrite) => ({ ...overwrite }));
462
845
  this.#context = context;
463
846
  }
464
847
  sendMessage(options) {
@@ -482,6 +865,11 @@ class Channel extends BaseStructure {
482
865
  editTopic(topic) {
483
866
  return this.edit({ topic });
484
867
  }
868
+ editPermissionOverwrite(targetId, changes, options) {
869
+ if (!this.#context?.editPermissionOverwrite)
870
+ throw new Error("This channel is not attached to a client.");
871
+ return this.#context.editPermissionOverwrite(this.id, targetId, changes, options);
872
+ }
485
873
  editParent(parentId) {
486
874
  return this.edit({ parent_id: parentId });
487
875
  }
@@ -616,6 +1004,7 @@ class Guild extends BaseStructure {
616
1004
  return this.name;
617
1005
  }
618
1006
  }
1007
+
619
1008
  // packages/core/src/permissions.ts
620
1009
  var Permission = {
621
1010
  createInstantInvite: 1n << 0n,
@@ -665,8 +1054,11 @@ var Permission = {
665
1054
  createEvents: 1n << 44n,
666
1055
  useExternalSounds: 1n << 45n,
667
1056
  sendVoiceMessages: 1n << 46n,
1057
+ setVoiceChannelStatus: 1n << 48n,
668
1058
  sendPolls: 1n << 49n,
669
- useExternalApps: 1n << 50n
1059
+ useExternalApps: 1n << 50n,
1060
+ pinMessages: 1n << 51n,
1061
+ bypassSlowmode: 1n << 52n
670
1062
  };
671
1063
  var Permissions = {
672
1064
  CreateInstantInvite: 1n << 0n,
@@ -716,8 +1108,11 @@ var Permissions = {
716
1108
  CreateEvents: 1n << 44n,
717
1109
  UseExternalSounds: 1n << 45n,
718
1110
  SendVoiceMessages: 1n << 46n,
1111
+ SetVoiceChannelStatus: 1n << 48n,
719
1112
  SendPolls: 1n << 49n,
720
- UseExternalApps: 1n << 50n
1113
+ UseExternalApps: 1n << 50n,
1114
+ PinMessages: 1n << 51n,
1115
+ BypassSlowmode: 1n << 52n
721
1116
  };
722
1117
  var PermissionFlagsBits = {
723
1118
  CreateInstantInvite: 1n << 0n,
@@ -767,8 +1162,11 @@ var PermissionFlagsBits = {
767
1162
  CreateEvents: 1n << 44n,
768
1163
  UseExternalSounds: 1n << 45n,
769
1164
  SendVoiceMessages: 1n << 46n,
1165
+ SetVoiceChannelStatus: 1n << 48n,
770
1166
  SendPolls: 1n << 49n,
771
- UseExternalApps: 1n << 50n
1167
+ UseExternalApps: 1n << 50n,
1168
+ PinMessages: 1n << 51n,
1169
+ BypassSlowmode: 1n << 52n
772
1170
  };
773
1171
 
774
1172
  class PermissionSet {
@@ -970,6 +1368,10 @@ class PermissionSet {
970
1368
  }
971
1369
  return false;
972
1370
  }
1371
+ missing(...permissions) {
1372
+ const wanted = new PermissionSet(permissions);
1373
+ return wanted.toArray().filter((name) => !this.has(name));
1374
+ }
973
1375
  add(...permissions) {
974
1376
  let bitfield = this.bitfield;
975
1377
  for (let i = 0;i < permissions.length; i++) {
@@ -995,6 +1397,11 @@ class PermissionSet {
995
1397
  toArray() {
996
1398
  return Object.keys(Permission).filter((permission) => this.has(permission));
997
1399
  }
1400
+ static #renamed = {
1401
+ ManageEmojisAndStickers: "ManageGuildExpressions",
1402
+ ManageEmojis: "ManageGuildExpressions",
1403
+ UseSlashCommands: "UseApplicationCommands"
1404
+ };
998
1405
  #resolve(permission) {
999
1406
  if (typeof permission === "bigint")
1000
1407
  return permission;
@@ -1009,6 +1416,9 @@ class PermissionSet {
1009
1416
  return bit;
1010
1417
  }
1011
1418
  if (typeof permission === "string") {
1419
+ const renamed = PermissionSet.#renamed[permission];
1420
+ if (renamed)
1421
+ return this.#resolve(renamed);
1012
1422
  if (permission in Permission)
1013
1423
  return Permission[permission];
1014
1424
  if (permission in Permissions)
@@ -1031,6 +1441,7 @@ class PermissionsBitField extends PermissionSet {
1031
1441
  super(value);
1032
1442
  }
1033
1443
  }
1444
+ var ALL_PERMISSIONS = Object.values(Permission).reduce((bits, bit) => bits | bit, 0n);
1034
1445
  // packages/types/src/gateway.ts
1035
1446
  var GatewayIntentBits = {
1036
1447
  Guilds: 1 << 0,
@@ -1129,13 +1540,15 @@ class GuildMember {
1129
1540
  roleIds;
1130
1541
  pending;
1131
1542
  joinedAt;
1132
- permissions;
1133
1543
  avatarHash;
1134
1544
  premiumSince;
1135
1545
  timedOutUntil;
1136
1546
  flags;
1137
- constructor(data) {
1547
+ #suppliedPermissions;
1548
+ #context;
1549
+ constructor(data, context) {
1138
1550
  this.user = new User(data.user);
1551
+ this.#context = context;
1139
1552
  if (!/^\d{1,20}$/.test(data.guild_id))
1140
1553
  throw new TypeError("Member guild_id must be a valid snowflake.");
1141
1554
  this.guildId = data.guild_id;
@@ -1145,12 +1558,53 @@ class GuildMember {
1145
1558
  this.joinedAt = data.joined_at ? new Date(data.joined_at) : undefined;
1146
1559
  if (this.joinedAt?.toString() === "Invalid Date")
1147
1560
  throw new RangeError("Member joined_at must be a valid date.");
1148
- this.permissions = new PermissionsBitField(data.permissions ?? 0n);
1561
+ if (data.permissions !== undefined)
1562
+ this.#suppliedPermissions = new PermissionsBitField(data.permissions);
1149
1563
  this.avatarHash = data.avatar ?? null;
1150
1564
  this.premiumSince = toDateOrNull(data.premium_since);
1151
1565
  this.timedOutUntil = toDateOrNull(data.communication_disabled_until);
1152
1566
  this.flags = data.flags ?? 0;
1153
1567
  }
1568
+ get permissions() {
1569
+ if (this.#suppliedPermissions)
1570
+ return this.#suppliedPermissions;
1571
+ return new PermissionsBitField(this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds) ?? 0n);
1572
+ }
1573
+ permissionsIn(channelId) {
1574
+ const computed = this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds, channelId);
1575
+ return computed ? new PermissionsBitField(computed) : null;
1576
+ }
1577
+ #action(name) {
1578
+ const action = this.#context?.[name];
1579
+ if (!action)
1580
+ throw new Error("This member is not attached to a client.");
1581
+ return action;
1582
+ }
1583
+ kick(reason) {
1584
+ return this.#action("kickMember")(this.guildId, this.user.id, reason);
1585
+ }
1586
+ ban(options = {}) {
1587
+ return this.#action("banMember")(this.guildId, this.user.id, options);
1588
+ }
1589
+ edit(options, reason) {
1590
+ return this.#action("editMember")(this.guildId, this.user.id, options, reason);
1591
+ }
1592
+ timeout(milliseconds, reason) {
1593
+ if (milliseconds !== null && !(milliseconds > 0))
1594
+ throw new RangeError("Timeout length must be a positive number of milliseconds.");
1595
+ return this.edit({
1596
+ communication_disabled_until: milliseconds === null ? null : new Date(Date.now() + milliseconds).toISOString()
1597
+ }, reason);
1598
+ }
1599
+ setNickname(nickname, reason) {
1600
+ return this.edit({ nick: nickname }, reason);
1601
+ }
1602
+ addRole(roleId, reason) {
1603
+ return this.#action("addMemberRole")(this.guildId, this.user.id, roleId, reason);
1604
+ }
1605
+ removeRole(roleId, reason) {
1606
+ return this.#action("removeMemberRole")(this.guildId, this.user.id, roleId, reason);
1607
+ }
1154
1608
  get displayName() {
1155
1609
  return this.nickname ?? this.user.displayName;
1156
1610
  }
@@ -1367,7 +1821,7 @@ class ForumChannel extends Channel {
1367
1821
 
1368
1822
  class MediaChannel extends ForumChannel {
1369
1823
  }
1370
- function createChannel(data, context) {
1824
+ function createChannel2(data, context) {
1371
1825
  switch (data.type) {
1372
1826
  case 0:
1373
1827
  return new TextChannel(data, context);
@@ -1394,7 +1848,11 @@ function createChannel(data, context) {
1394
1848
  return new Channel(data, context);
1395
1849
  }
1396
1850
  }
1851
+ // packages/structures/src/interactions.ts
1852
+ var TOKEN_LIFETIME_MS = 15 * 60000;
1853
+
1397
1854
  // packages/structures/src/index.ts
1855
+ var COMPONENT_COLLECTOR_DEFAULT_TIME = 15 * 60000;
1398
1856
  var NON_SYSTEM_MESSAGE_TYPES = new Set([0, 19, 20, 23]);
1399
1857
 
1400
1858
  class Message extends BaseStructure {
@@ -1415,6 +1873,7 @@ class Message extends BaseStructure {
1415
1873
  reference;
1416
1874
  components;
1417
1875
  referencedMessage;
1876
+ member;
1418
1877
  #context;
1419
1878
  constructor(data, context) {
1420
1879
  super(data.id);
@@ -1437,6 +1896,11 @@ class Message extends BaseStructure {
1437
1896
  this.reference = data.message_reference;
1438
1897
  this.referencedMessage = data.referenced_message ? new Message(data.referenced_message, context) : data.referenced_message === null ? null : undefined;
1439
1898
  this.#context = context;
1899
+ this.member = data.member && data.guild_id ? new GuildMember({
1900
+ ...data.member,
1901
+ user: data.member.user ?? data.author,
1902
+ guild_id: data.guild_id
1903
+ }, context) : null;
1440
1904
  this.channel = new Channel({ id: data.channel_id, type: 0, guild_id: data.guild_id }, context);
1441
1905
  }
1442
1906
  get embedsSuppressed() {
@@ -1477,6 +1941,20 @@ class Message extends BaseStructure {
1477
1941
  throw new Error("This message is not attached to a client.");
1478
1942
  return this.#context.crosspostMessage(this.channelId, this.id);
1479
1943
  }
1944
+ createComponentCollector(options = {}) {
1945
+ const collect = this.#context?.collectInteractions;
1946
+ if (!collect)
1947
+ throw new Error("This message is not attached to a client.");
1948
+ const { componentType, filter, ...rest } = options;
1949
+ return collect({
1950
+ ...rest,
1951
+ time: rest.time ?? (rest.idle ? undefined : COMPONENT_COLLECTOR_DEFAULT_TIME),
1952
+ filter: async (interaction) => interaction.isMessageComponent() && interaction.messageId === this.id && (componentType === undefined || interaction.componentType === componentType) && (filter ? await filter(interaction) : true)
1953
+ });
1954
+ }
1955
+ awaitComponent(options = {}) {
1956
+ return this.createComponentCollector({ ...options, max: 1 }).next();
1957
+ }
1480
1958
  react(emoji) {
1481
1959
  if (!this.#context?.addReaction)
1482
1960
  throw new Error("This message is not attached to a client.");
@@ -1550,23 +2028,43 @@ class Message extends BaseStructure {
1550
2028
  }
1551
2029
 
1552
2030
  // packages/managers/src/message.ts
2031
+ function toRequest(options) {
2032
+ const { files, ...body } = options;
2033
+ if (!files?.length)
2034
+ return body;
2035
+ return {
2036
+ body,
2037
+ files: files.map((file) => ({
2038
+ name: file.name,
2039
+ data: typeof file.data === "string" ? new TextEncoder().encode(file.data) : file.data,
2040
+ contentType: file.contentType
2041
+ }))
2042
+ };
2043
+ }
2044
+
1553
2045
  class MessageManager {
1554
- cache = new Collection;
2046
+ cache;
2047
+ #caching;
1555
2048
  #rest;
1556
2049
  #context;
1557
2050
  #channelId;
1558
- constructor(rest, context, channelId) {
2051
+ constructor(rest, context, channelId, cache) {
1559
2052
  if (!channelId)
1560
2053
  throw new TypeError("Channel ID is required.");
1561
2054
  this.#rest = rest;
1562
2055
  this.#context = context;
1563
2056
  this.#channelId = channelId;
2057
+ this.#caching = cache !== undefined;
2058
+ this.cache = new Collection(null, {
2059
+ ttl: cache?.ttl,
2060
+ maxSize: cache ? cache.maxSize ?? 100 : undefined
2061
+ });
1564
2062
  }
1565
2063
  async resolve(messageId) {
1566
2064
  return this.cache.get(messageId) ?? this.fetch(messageId);
1567
2065
  }
1568
2066
  async send(options) {
1569
- const data = await this.#rest.post(Routes.channelMessages(this.#channelId), options);
2067
+ const data = await this.#rest.post(Routes.channelMessages(this.#channelId), toRequest(options));
1570
2068
  return this.upsert(data);
1571
2069
  }
1572
2070
  async fetch(messageId) {
@@ -1577,13 +2075,14 @@ class MessageManager {
1577
2075
  return Promise.all(Array.from(messageIds, (messageId) => this.fetch(messageId)));
1578
2076
  }
1579
2077
  upsert(data) {
1580
- const existing = this.cache.get(data.id);
2078
+ const existing = this.cache.peek(data.id);
1581
2079
  const message = new Message(data, this.#context);
1582
2080
  if (existing) {
1583
2081
  Object.assign(existing, message);
1584
2082
  return existing;
1585
2083
  }
1586
- this.cache.set(message.id, message);
2084
+ if (this.#caching)
2085
+ this.cache.set(message.id, message);
1587
2086
  return message;
1588
2087
  }
1589
2088
  delete(messageId) {
@@ -1609,7 +2108,7 @@ class ThreadManager {
1609
2108
  auto_archive_duration: options.autoArchiveDuration,
1610
2109
  rate_limit_per_user: options.rateLimitPerUser
1611
2110
  });
1612
- return createChannel(data, this.#context);
2111
+ return createChannel2(data, this.#context);
1613
2112
  }
1614
2113
  }
1615
2114
 
@@ -1637,8 +2136,301 @@ class UserManager extends ResourceManager {
1637
2136
  });
1638
2137
  }
1639
2138
  }
2139
+ // packages/managers/src/emoji.ts
2140
+ class EmojiManager extends Manager {
2141
+ #rest;
2142
+ #guildId;
2143
+ constructor(rest, guildId) {
2144
+ super();
2145
+ this.#rest = rest;
2146
+ this.#guildId = guildId;
2147
+ }
2148
+ fetch(emojiId) {
2149
+ return this.fetchOnce(emojiId, async () => new Emoji(await this.#rest.get(Routes.guildEmoji(this.#guildId, emojiId))), (emoji) => this.#merge(emojiId, emoji));
2150
+ }
2151
+ async fetchAll() {
2152
+ const data = await this.#rest.get(Routes.guildEmoji(this.#guildId));
2153
+ return data.map((item) => this.upsert(item));
2154
+ }
2155
+ async create(options) {
2156
+ return this.upsert(await this.#rest.post(Routes.guildEmoji(this.#guildId), options));
2157
+ }
2158
+ async edit(emojiId, options) {
2159
+ return this.upsert(await this.#rest.patch(Routes.guildEmoji(this.#guildId, emojiId), options));
2160
+ }
2161
+ async deleteEmoji(emojiId) {
2162
+ await this.#rest.delete(Routes.guildEmoji(this.#guildId, emojiId));
2163
+ this.delete(emojiId);
2164
+ }
2165
+ upsert(data) {
2166
+ const key = data.id != null ? data.id : `unicode:${data.name ?? ""}`;
2167
+ return this.#merge(key, new Emoji(data));
2168
+ }
2169
+ #merge(key, emoji) {
2170
+ const existing = this.get(key);
2171
+ if (existing) {
2172
+ Object.assign(existing, emoji);
2173
+ return existing;
2174
+ }
2175
+ this.set(key, emoji);
2176
+ return emoji;
2177
+ }
2178
+ }
2179
+
2180
+ // packages/managers/src/advanced.ts
2181
+ function withQuery(path, query) {
2182
+ const params = new URLSearchParams;
2183
+ for (const [key, value] of Object.entries(query))
2184
+ if (value !== undefined)
2185
+ params.set(key, String(value));
2186
+ const suffix = params.toString();
2187
+ return suffix ? `${path}?${suffix}` : path;
2188
+ }
2189
+
2190
+ class GuildStickerManager extends Manager {
2191
+ #rest;
2192
+ guildId;
2193
+ constructor(rest, guildId) {
2194
+ super();
2195
+ this.#rest = rest;
2196
+ this.guildId = guildId;
2197
+ }
2198
+ #store(sticker) {
2199
+ this.set(sticker.id, sticker);
2200
+ return sticker;
2201
+ }
2202
+ async fetchAll() {
2203
+ const stickers = await this.#rest.get(Routes.guildSticker(this.guildId));
2204
+ this.clear();
2205
+ return stickers.map((sticker) => this.#store(sticker));
2206
+ }
2207
+ async fetch(stickerId) {
2208
+ return this.#store(await this.#rest.get(Routes.guildSticker(this.guildId, stickerId)));
2209
+ }
2210
+ async create(options) {
2211
+ const form = new FormData;
2212
+ form.set("name", options.name);
2213
+ form.set("description", options.description);
2214
+ form.set("tags", options.tags);
2215
+ form.set("file", options.file);
2216
+ return this.#store(await this.#rest.post(Routes.guildSticker(this.guildId), form, { reason: options.reason }));
2217
+ }
2218
+ async edit(stickerId, options) {
2219
+ const { reason, ...body } = options;
2220
+ return this.#store(await this.#rest.patch(Routes.guildSticker(this.guildId, stickerId), body, { reason }));
2221
+ }
2222
+ async remove(stickerId, reason) {
2223
+ await this.#rest.delete(Routes.guildSticker(this.guildId, stickerId), {
2224
+ reason
2225
+ });
2226
+ this.delete(stickerId);
2227
+ }
2228
+ sync(stickers) {
2229
+ this.clear();
2230
+ for (const sticker of stickers)
2231
+ this.#store(sticker);
2232
+ }
2233
+ }
2234
+
2235
+ class GuildSoundboardManager extends Manager {
2236
+ #rest;
2237
+ guildId;
2238
+ constructor(rest, guildId) {
2239
+ super();
2240
+ this.#rest = rest;
2241
+ this.guildId = guildId;
2242
+ }
2243
+ #store(sound) {
2244
+ this.set(sound.sound_id, sound);
2245
+ return sound;
2246
+ }
2247
+ async fetchAll() {
2248
+ const { items } = await this.#rest.get(Routes.guildSoundboardSound(this.guildId));
2249
+ this.clear();
2250
+ return items.map((sound) => this.#store(sound));
2251
+ }
2252
+ async fetch(soundId) {
2253
+ return this.#store(await this.#rest.get(Routes.guildSoundboardSound(this.guildId, soundId)));
2254
+ }
2255
+ async create(options) {
2256
+ if (options.volume !== undefined && (options.volume < 0 || options.volume > 1))
2257
+ throw new RangeError("Soundboard volume must be between 0 and 1.");
2258
+ return this.#store(await this.#rest.post(Routes.guildSoundboardSound(this.guildId), {
2259
+ name: options.name,
2260
+ sound: options.sound,
2261
+ volume: options.volume,
2262
+ emoji_id: options.emojiId,
2263
+ emoji_name: options.emojiName
2264
+ }, { reason: options.reason }));
2265
+ }
2266
+ async edit(soundId, options) {
2267
+ return this.#store(await this.#rest.patch(Routes.guildSoundboardSound(this.guildId, soundId), {
2268
+ name: options.name,
2269
+ volume: options.volume,
2270
+ emoji_id: options.emojiId,
2271
+ emoji_name: options.emojiName
2272
+ }, { reason: options.reason }));
2273
+ }
2274
+ async remove(soundId, reason) {
2275
+ await this.#rest.delete(Routes.guildSoundboardSound(this.guildId, soundId), { reason });
2276
+ this.delete(soundId);
2277
+ }
2278
+ }
2279
+
2280
+ class MonetizationManager extends Manager {
2281
+ #rest;
2282
+ applicationId;
2283
+ constructor(rest, applicationId) {
2284
+ super();
2285
+ this.#rest = rest;
2286
+ this.applicationId = applicationId;
2287
+ }
2288
+ fetchSkus() {
2289
+ return this.#rest.get(Routes.applicationSkus(this.applicationId));
2290
+ }
2291
+ async fetchEntitlements(query = {}) {
2292
+ if (query.limit !== undefined && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 100))
2293
+ throw new RangeError("Entitlement limit must be 1-100.");
2294
+ const entitlements = await this.#rest.get(withQuery(Routes.applicationEntitlement(this.applicationId), {
2295
+ user_id: query.userId,
2296
+ sku_ids: query.skuIds?.join(","),
2297
+ guild_id: query.guildId,
2298
+ before: query.before,
2299
+ after: query.after,
2300
+ limit: query.limit,
2301
+ exclude_ended: query.excludeEnded,
2302
+ exclude_deleted: query.excludeDeleted
2303
+ }));
2304
+ for (const entitlement of entitlements)
2305
+ this.set(entitlement.id, entitlement);
2306
+ return entitlements;
2307
+ }
2308
+ async fetch(entitlementId) {
2309
+ const entitlement = await this.#rest.get(Routes.applicationEntitlement(this.applicationId, entitlementId));
2310
+ this.set(entitlement.id, entitlement);
2311
+ return entitlement;
2312
+ }
2313
+ async consume(entitlementId) {
2314
+ await this.#rest.post(Routes.consumeEntitlement(this.applicationId, entitlementId));
2315
+ const cached = this.get(entitlementId);
2316
+ if (cached)
2317
+ cached.consumed = true;
2318
+ }
2319
+ async createTestEntitlement(options) {
2320
+ const entitlement = await this.#rest.post(Routes.applicationEntitlement(this.applicationId), {
2321
+ sku_id: options.skuId,
2322
+ owner_id: options.ownerId,
2323
+ owner_type: options.ownerType
2324
+ });
2325
+ this.set(entitlement.id, entitlement);
2326
+ return entitlement;
2327
+ }
2328
+ async deleteTestEntitlement(entitlementId) {
2329
+ await this.#rest.delete(Routes.applicationEntitlement(this.applicationId, entitlementId));
2330
+ this.delete(entitlementId);
2331
+ }
2332
+ fetchSubscriptions(skuId, query = {}) {
2333
+ return this.#rest.get(withQuery(Routes.skuSubscription(skuId), {
2334
+ user_id: query.userId,
2335
+ before: query.before,
2336
+ after: query.after,
2337
+ limit: query.limit
2338
+ }));
2339
+ }
2340
+ fetchSubscription(skuId, subscriptionId) {
2341
+ return this.#rest.get(Routes.skuSubscription(skuId, subscriptionId));
2342
+ }
2343
+ }
2344
+
2345
+ // packages/managers/src/member.ts
2346
+ class GuildMemberManager extends ResourceManager {
2347
+ #rest;
2348
+ #context;
2349
+ guildId;
2350
+ constructor(guildId, rest, context = () => {
2351
+ return;
2352
+ }) {
2353
+ super((id) => rest.get(Routes.guildMember(guildId, id)).then((data) => new GuildMember({ ...data, guild_id: guildId }, context())), (member) => member.user.id);
2354
+ this.guildId = guildId;
2355
+ this.#rest = rest;
2356
+ this.#context = context;
2357
+ }
2358
+ async kick(userId, reason) {
2359
+ await this.#rest.delete(Routes.guildMember(this.guildId, userId), {
2360
+ reason
2361
+ });
2362
+ this.delete(userId);
2363
+ }
2364
+ async ban(userId, options = {}) {
2365
+ await this.#rest.put(Routes.guildBan(this.guildId, userId), { delete_message_seconds: options.deleteMessageSeconds }, { reason: options.reason });
2366
+ this.delete(userId);
2367
+ }
2368
+ async unban(userId) {
2369
+ await this.#rest.delete(Routes.guildBan(this.guildId, userId));
2370
+ }
2371
+ async edit(userId, options, reason) {
2372
+ const data = await this.#rest.patch(Routes.guildMember(this.guildId, userId), options, { reason });
2373
+ const member = new GuildMember({ ...data, guild_id: this.guildId }, this.#context());
2374
+ this.set(member.user.id, member);
2375
+ return member;
2376
+ }
2377
+ async addRole(userId, roleId, reason) {
2378
+ await this.#rest.put(Routes.guildMemberRole(this.guildId, userId, roleId), undefined, { reason });
2379
+ }
2380
+ async removeRole(userId, roleId, reason) {
2381
+ await this.#rest.delete(Routes.guildMemberRole(this.guildId, userId, roleId), { reason });
2382
+ }
2383
+ async timeout(userId, milliseconds, reason) {
2384
+ const timeoutDate = milliseconds === null ? null : new Date(Date.now() + milliseconds).toISOString();
2385
+ return this.edit(userId, { communication_disabled_until: timeoutDate }, reason);
2386
+ }
2387
+ }
2388
+
2389
+ // packages/managers/src/role.ts
2390
+ class RoleManager extends ResourceManager {
2391
+ #rest;
2392
+ guildId;
2393
+ constructor(guildId, rest) {
2394
+ super((id) => rest.get(Routes.guildRole(guildId, id)).then((data) => new Role(data)), (role) => role.id);
2395
+ this.guildId = guildId;
2396
+ this.#rest = rest;
2397
+ }
2398
+ async fetchAll() {
2399
+ const data = await this.#rest.get(Routes.guildRoles(this.guildId));
2400
+ return data.map((item) => {
2401
+ const role = new Role(item);
2402
+ this.set(role.id, role);
2403
+ return role;
2404
+ });
2405
+ }
2406
+ async create(options) {
2407
+ const { reason, ...payload } = options;
2408
+ const data = await this.#rest.post(Routes.guildRoles(this.guildId), {
2409
+ ...payload,
2410
+ permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
2411
+ });
2412
+ const role = new Role(data);
2413
+ this.set(role.id, role);
2414
+ return role;
2415
+ }
2416
+ async edit(roleId, options) {
2417
+ const { reason, ...payload } = options;
2418
+ const data = await this.#rest.patch(Routes.guildRole(this.guildId, roleId), {
2419
+ ...payload,
2420
+ permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
2421
+ });
2422
+ const role = new Role(data);
2423
+ this.set(role.id, role);
2424
+ return role;
2425
+ }
2426
+ async deleteRole(roleId) {
2427
+ await this.#rest.delete(Routes.guildRole(this.guildId, roleId));
2428
+ this.delete(roleId);
2429
+ }
2430
+ }
2431
+
1640
2432
  // packages/managers/src/guild-resources.ts
1641
- function withQuery(path, params) {
2433
+ function withQuery2(path, params) {
1642
2434
  const query = new URLSearchParams;
1643
2435
  for (const [key, value] of Object.entries(params))
1644
2436
  if (value !== undefined)
@@ -1662,7 +2454,7 @@ class GuildBanManager extends Manager {
1662
2454
  }
1663
2455
  async fetchAll(options = {}) {
1664
2456
  const limit = options.limit === undefined ? undefined : Math.min(1000, Math.max(1, options.limit));
1665
- const bans = await this.#rest.get(withQuery(Routes.guildBans(this.guildId), {
2457
+ const bans = await this.#rest.get(withQuery2(Routes.guildBans(this.guildId), {
1666
2458
  limit,
1667
2459
  before: options.before,
1668
2460
  after: options.after
@@ -1695,12 +2487,12 @@ class GuildScheduledEventManager extends Manager {
1695
2487
  return event;
1696
2488
  }
1697
2489
  async fetch(eventId, options = {}) {
1698
- return this.#store(await this.#rest.get(withQuery(Routes.guildScheduledEvent(this.guildId, eventId), {
2490
+ return this.#store(await this.#rest.get(withQuery2(Routes.guildScheduledEvent(this.guildId, eventId), {
1699
2491
  with_user_count: options.withUserCount
1700
2492
  })));
1701
2493
  }
1702
2494
  async fetchAll(options = {}) {
1703
- const events = await this.#rest.get(withQuery(Routes.guildScheduledEvents(this.guildId), {
2495
+ const events = await this.#rest.get(withQuery2(Routes.guildScheduledEvents(this.guildId), {
1704
2496
  with_user_count: options.withUserCount
1705
2497
  }));
1706
2498
  return events.map((event) => this.#store(event));
@@ -1717,7 +2509,7 @@ class GuildScheduledEventManager extends Manager {
1717
2509
  }
1718
2510
  async fetchSubscribers(eventId, options = {}) {
1719
2511
  const limit = options.limit === undefined ? undefined : Math.min(100, Math.max(1, options.limit));
1720
- return this.#rest.get(withQuery(Routes.guildScheduledEventUsers(this.guildId, eventId), {
2512
+ return this.#rest.get(withQuery2(Routes.guildScheduledEventUsers(this.guildId, eventId), {
1721
2513
  limit,
1722
2514
  with_member: options.withMember,
1723
2515
  before: options.before,
@@ -1761,10 +2553,25 @@ class StageInstanceManager extends Manager {
1761
2553
 
1762
2554
  class PermissionOverwriteManager {
1763
2555
  #rest;
2556
+ #current;
1764
2557
  channelId;
1765
- constructor(rest, channelId) {
2558
+ constructor(rest, channelId, current = () => {
2559
+ return;
2560
+ }) {
1766
2561
  this.#rest = rest;
1767
2562
  this.channelId = channelId;
2563
+ this.#current = current;
2564
+ }
2565
+ async update(overwriteId, changes, options = {}) {
2566
+ const overwrites = this.#current() ?? (await this.#rest.get(Routes.channel(this.channelId))).permission_overwrites ?? [];
2567
+ const existing = overwrites.find((entry) => entry.id === overwriteId);
2568
+ const type = existing?.type ?? options.type;
2569
+ if (type !== 0 && type !== 1)
2570
+ throw new TypeError("A new permission overwrite needs a type: 0 for a role, 1 for a member.");
2571
+ const touched = (changes.allow ?? 0n) | (changes.deny ?? 0n) | (changes.inherit ?? 0n);
2572
+ const allow = BigInt(existing?.allow ?? 0) & ~touched | (changes.allow ?? 0n);
2573
+ const deny = BigInt(existing?.deny ?? 0) & ~touched | (changes.deny ?? 0n);
2574
+ await this.edit(overwriteId, { type, allow, deny }, options.reason);
1768
2575
  }
1769
2576
  async edit(overwriteId, options, reason) {
1770
2577
  await this.#rest.put(Routes.channelPermission(this.channelId, overwriteId), {
@@ -1779,7 +2586,7 @@ class PermissionOverwriteManager {
1779
2586
  }
1780
2587
 
1781
2588
  // packages/managers/src/guild.ts
1782
- function withQuery2(path, params) {
2589
+ function withQuery3(path, params) {
1783
2590
  const suffix = params.toString();
1784
2591
  return suffix ? `${path}?${suffix}` : path;
1785
2592
  }
@@ -1788,6 +2595,24 @@ class GuildManager extends ResourceManager {
1788
2595
  #rest;
1789
2596
  #bans = new Map;
1790
2597
  #scheduledEvents = new Map;
2598
+ #members = new Map;
2599
+ #roles = new Map;
2600
+ #emojis = new Map;
2601
+ #stickers = new Map;
2602
+ #soundboard = new Map;
2603
+ #voiceStates = new Map;
2604
+ #autoModerationRules = new Map;
2605
+ #invites = new Map;
2606
+ #context;
2607
+ attachContext(context) {
2608
+ this.#context = context;
2609
+ }
2610
+ #perGuild(map, guildId, create) {
2611
+ let manager = map.get(guildId);
2612
+ if (!manager)
2613
+ map.set(guildId, manager = create());
2614
+ return manager;
2615
+ }
1791
2616
  constructor(rest) {
1792
2617
  super(async (id) => new Guild(await rest.get(Routes.guild(id))), (guild) => guild.id);
1793
2618
  this.#rest = rest;
@@ -1804,6 +2629,68 @@ class GuildManager extends ResourceManager {
1804
2629
  this.#scheduledEvents.set(guildId, manager = new GuildScheduledEventManager(this.#rest, guildId));
1805
2630
  return manager;
1806
2631
  }
2632
+ members(guildId) {
2633
+ let manager = this.#members.get(guildId);
2634
+ if (!manager)
2635
+ this.#members.set(guildId, manager = new GuildMemberManager(guildId, this.#rest, () => this.#context));
2636
+ return manager;
2637
+ }
2638
+ roles(guildId) {
2639
+ let manager = this.#roles.get(guildId);
2640
+ if (!manager)
2641
+ this.#roles.set(guildId, manager = new RoleManager(guildId, this.#rest));
2642
+ return manager;
2643
+ }
2644
+ emojis(guildId) {
2645
+ let manager = this.#emojis.get(guildId);
2646
+ if (!manager)
2647
+ this.#emojis.set(guildId, manager = new EmojiManager(this.#rest, guildId));
2648
+ return manager;
2649
+ }
2650
+ stickers(guildId) {
2651
+ let manager = this.#stickers.get(guildId);
2652
+ if (!manager)
2653
+ this.#stickers.set(guildId, manager = new GuildStickerManager(this.#rest, guildId));
2654
+ return manager;
2655
+ }
2656
+ soundboard(guildId) {
2657
+ let manager = this.#soundboard.get(guildId);
2658
+ if (!manager)
2659
+ this.#soundboard.set(guildId, manager = new GuildSoundboardManager(this.#rest, guildId));
2660
+ return manager;
2661
+ }
2662
+ voiceStates(guildId) {
2663
+ return this.#perGuild(this.#voiceStates, guildId, () => new Manager);
2664
+ }
2665
+ autoModerationRules(guildId) {
2666
+ return this.#perGuild(this.#autoModerationRules, guildId, () => new Manager);
2667
+ }
2668
+ invites(guildId) {
2669
+ return this.#perGuild(this.#invites, guildId, () => new Manager);
2670
+ }
2671
+ patch(data) {
2672
+ const guild = new Guild(data);
2673
+ const existing = this.get(guild.id);
2674
+ if (!existing)
2675
+ return this.upsert(guild);
2676
+ for (const [key, value] of Object.entries(guild))
2677
+ if (value !== undefined)
2678
+ existing[key] = value;
2679
+ return existing;
2680
+ }
2681
+ delete(id) {
2682
+ this.#bans.delete(id);
2683
+ this.#scheduledEvents.delete(id);
2684
+ this.#members.delete(id);
2685
+ this.#roles.delete(id);
2686
+ this.#emojis.delete(id);
2687
+ this.#stickers.delete(id);
2688
+ this.#soundboard.delete(id);
2689
+ this.#voiceStates.delete(id);
2690
+ this.#autoModerationRules.delete(id);
2691
+ this.#invites.delete(id);
2692
+ return super.delete(id);
2693
+ }
1807
2694
  async create(options) {
1808
2695
  const data = await this.#rest.post("/guilds", options);
1809
2696
  return this.upsert(new Guild(data));
@@ -1839,7 +2726,7 @@ class GuildManager extends ResourceManager {
1839
2726
  params.set("after", options.after);
1840
2727
  if (options.limit !== undefined)
1841
2728
  params.set("limit", String(Math.min(100, Math.max(1, options.limit))));
1842
- return this.#rest.get(withQuery2(Routes.guildAuditLog(guildId), params));
2729
+ return this.#rest.get(withQuery3(Routes.guildAuditLog(guildId), params));
1843
2730
  }
1844
2731
  async fetchMembers(guildId, options = {}) {
1845
2732
  const params = new URLSearchParams;
@@ -1847,7 +2734,7 @@ class GuildManager extends ResourceManager {
1847
2734
  params.set("limit", String(Math.min(1000, Math.max(1, options.limit))));
1848
2735
  if (options.after)
1849
2736
  params.set("after", options.after);
1850
- return this.#rest.get(withQuery2(Routes.guildMembers(guildId), params));
2737
+ return this.#rest.get(withQuery3(Routes.guildMembers(guildId), params));
1851
2738
  }
1852
2739
  async fetchAutoModerationRules(guildId) {
1853
2740
  const rules = await this.#rest.get(Routes.guildAutoModerationRules(guildId));
@@ -1922,85 +2809,6 @@ var AuditLogEvent = {
1922
2809
  AutoModerationRuleDelete: 142,
1923
2810
  AutoModerationBlockMessage: 143
1924
2811
  };
1925
- // packages/managers/src/role.ts
1926
- class RoleManager extends ResourceManager {
1927
- #rest;
1928
- guildId;
1929
- constructor(guildId, rest) {
1930
- super((id) => rest.get(Routes.guildRole(guildId, id)).then((data) => new Role(data)), (role) => role.id);
1931
- this.guildId = guildId;
1932
- this.#rest = rest;
1933
- }
1934
- async fetchAll() {
1935
- const data = await this.#rest.get(Routes.guildRoles(this.guildId));
1936
- return data.map((item) => {
1937
- const role = new Role(item);
1938
- this.set(role.id, role);
1939
- return role;
1940
- });
1941
- }
1942
- async create(options) {
1943
- const { reason, ...payload } = options;
1944
- const data = await this.#rest.post(Routes.guildRoles(this.guildId), {
1945
- ...payload,
1946
- permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
1947
- });
1948
- const role = new Role(data);
1949
- this.set(role.id, role);
1950
- return role;
1951
- }
1952
- async edit(roleId, options) {
1953
- const { reason, ...payload } = options;
1954
- const data = await this.#rest.patch(Routes.guildRole(this.guildId, roleId), {
1955
- ...payload,
1956
- permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
1957
- });
1958
- const role = new Role(data);
1959
- this.set(role.id, role);
1960
- return role;
1961
- }
1962
- async deleteRole(roleId) {
1963
- await this.#rest.delete(Routes.guildRole(this.guildId, roleId));
1964
- this.delete(roleId);
1965
- }
1966
- }
1967
- // packages/managers/src/member.ts
1968
- class GuildMemberManager extends ResourceManager {
1969
- #rest;
1970
- guildId;
1971
- constructor(guildId, rest) {
1972
- super((id) => rest.get(Routes.guildMember(guildId, id)).then((data) => new GuildMember({ ...data, guild_id: guildId })), (member) => member.user.id);
1973
- this.guildId = guildId;
1974
- this.#rest = rest;
1975
- }
1976
- async kick(userId) {
1977
- await this.#rest.delete(Routes.guildMember(this.guildId, userId));
1978
- this.delete(userId);
1979
- }
1980
- async ban(userId, options = {}) {
1981
- await this.#rest.put(Routes.guildBan(this.guildId, userId), { delete_message_seconds: options.deleteMessageSeconds }, { reason: options.reason });
1982
- this.delete(userId);
1983
- }
1984
- async unban(userId) {
1985
- await this.#rest.delete(Routes.guildBan(this.guildId, userId));
1986
- }
1987
- async edit(userId, options) {
1988
- const data = await this.#rest.patch(Routes.guildMember(this.guildId, userId), options);
1989
- const member = new GuildMember({ ...data, guild_id: this.guildId });
1990
- this.set(member.user.id, member);
1991
- return member;
1992
- }
1993
- async addRole(userId, roleId) {
1994
- await this.#rest.put(Routes.guildMemberRole(this.guildId, userId, roleId));
1995
- }
1996
- async removeRole(userId, roleId) {
1997
- await this.#rest.delete(Routes.guildMemberRole(this.guildId, userId, roleId));
1998
- }
1999
- async timeout(userId, milliseconds) {
2000
- const timeoutDate = milliseconds === null ? null : new Date(Date.now() + milliseconds).toISOString();
2001
- return this.edit(userId, { communication_disabled_until: timeoutDate });
2002
- }
2003
- }
2004
2812
  // packages/managers/src/application.ts
2005
2813
  class ApplicationCommandManager {
2006
2814
  #rest;
@@ -2040,53 +2848,22 @@ class ApplicationCommandManager {
2040
2848
  await this.#rest.delete(Routes.guildApplicationCommand(this.#applicationId, guildId, commandId));
2041
2849
  }
2042
2850
  }
2043
- // packages/managers/src/emoji.ts
2044
- class EmojiManager extends Manager {
2045
- #rest;
2046
- #guildId;
2047
- constructor(rest, guildId) {
2048
- super();
2049
- this.#rest = rest;
2050
- this.#guildId = guildId;
2051
- }
2052
- async fetch(emojiId) {
2053
- return this.upsert(await this.#rest.get(Routes.guildEmoji(this.#guildId, emojiId)));
2054
- }
2055
- async fetchAll() {
2056
- const data = await this.#rest.get(Routes.guildEmoji(this.#guildId));
2057
- return data.map((item) => this.upsert(item));
2058
- }
2059
- async create(options) {
2060
- return this.upsert(await this.#rest.post(Routes.guildEmoji(this.#guildId), options));
2061
- }
2062
- async edit(emojiId, options) {
2063
- return this.upsert(await this.#rest.patch(Routes.guildEmoji(this.#guildId, emojiId), options));
2064
- }
2065
- async deleteEmoji(emojiId) {
2066
- await this.#rest.delete(Routes.guildEmoji(this.#guildId, emojiId));
2067
- this.delete(emojiId);
2068
- }
2069
- upsert(data) {
2070
- const key = data.id != null ? data.id : `unicode:${data.name ?? ""}`;
2071
- const existing = this.get(key);
2072
- const emoji = new Emoji(data);
2073
- if (existing) {
2074
- Object.assign(existing, emoji);
2075
- return existing;
2076
- }
2077
- this.set(key, emoji);
2078
- return emoji;
2079
- }
2080
- }
2081
2851
 
2082
2852
  // packages/managers/src/index.ts
2853
+ var BULK_DELETE_MAX_AGE_MS = 14 * 24 * 60 * 60000;
2854
+ function snowflakeTime(id) {
2855
+ return Number((BigInt(id) >> 22n) + 1420070400000n);
2856
+ }
2857
+
2083
2858
  class ChannelManager extends Manager {
2084
2859
  #rest;
2085
2860
  #context;
2086
2861
  #messageManagers = new Map;
2087
- constructor(rest) {
2862
+ #messageCache;
2863
+ constructor(rest, options = {}) {
2088
2864
  super();
2089
2865
  this.#rest = rest;
2866
+ this.#messageCache = options.messageCache;
2090
2867
  this.#context = {
2091
2868
  sendMessage: (channelId, options) => this.send(channelId, options),
2092
2869
  editMessage: (channelId, messageId, options) => this.editMessage(channelId, messageId, options),
@@ -2105,27 +2882,29 @@ class ChannelManager extends Manager {
2105
2882
  messages(channelId) {
2106
2883
  let manager = this.#messageManagers.get(channelId);
2107
2884
  if (!manager) {
2108
- manager = new MessageManager(this.#rest, this.#context, channelId);
2885
+ manager = new MessageManager(this.#rest, this.#context, channelId, this.#messageCache);
2109
2886
  this.#messageManagers.set(channelId, manager);
2110
2887
  }
2111
2888
  return manager;
2112
2889
  }
2113
2890
  permissionOverwrites(channelId) {
2114
- return new PermissionOverwriteManager(this.#rest, channelId);
2891
+ return new PermissionOverwriteManager(this.#rest, channelId, () => this.get(channelId)?.permissionOverwrites);
2115
2892
  }
2116
2893
  threads(channelId) {
2117
2894
  return new ThreadManager(this.#rest, this.#context, channelId);
2118
2895
  }
2119
- async fetch(channelId) {
2120
- return this.upsert(await this.#rest.get(Routes.channel(channelId)));
2896
+ fetch(channelId) {
2897
+ return this.fetchOnce(channelId, async () => createChannel2(await this.#rest.get(Routes.channel(channelId)), this.#context), (channel) => this.#merge(channel));
2121
2898
  }
2122
2899
  async resolve(channelId) {
2123
2900
  return this.get(channelId) ?? this.fetch(channelId);
2124
2901
  }
2125
2902
  upsert(data) {
2126
- const existing = this.get(data.id);
2127
- const channel = createChannel(data, this.#context);
2128
- if (existing) {
2903
+ return this.#merge(createChannel2(data, this.#context));
2904
+ }
2905
+ #merge(channel) {
2906
+ const existing = this.get(channel.id);
2907
+ if (existing && existing.type === channel.type) {
2129
2908
  Object.assign(existing, channel);
2130
2909
  return existing;
2131
2910
  }
@@ -2135,6 +2914,37 @@ class ChannelManager extends Manager {
2135
2914
  update(channel) {
2136
2915
  return this.set(channel.id, channel);
2137
2916
  }
2917
+ deleteGuildChannels(guildId) {
2918
+ let removed = 0;
2919
+ for (const channel of this.values())
2920
+ if (channel.guildId === guildId && this.delete(channel.id))
2921
+ removed++;
2922
+ return removed;
2923
+ }
2924
+ async endPoll(channelId, messageId) {
2925
+ return this.messages(channelId).upsert(await this.#rest.post(Routes.pollExpire(channelId, messageId)));
2926
+ }
2927
+ async fetchPollVoters(channelId, messageId, answerId, options = {}) {
2928
+ if (options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100))
2929
+ throw new RangeError("Poll voter limit must be 1-100.");
2930
+ const params = new URLSearchParams;
2931
+ if (options.after)
2932
+ params.set("after", options.after);
2933
+ if (options.limit !== undefined)
2934
+ params.set("limit", String(options.limit));
2935
+ const suffix = params.toString();
2936
+ const { users } = await this.#rest.get(`${Routes.pollAnswerVoters(channelId, messageId, answerId)}${suffix ? `?${suffix}` : ""}`);
2937
+ return users.map((user) => new User(user));
2938
+ }
2939
+ async sendSoundboardSound(channelId, options) {
2940
+ await this.#rest.post(Routes.sendSoundboardSound(channelId), {
2941
+ sound_id: options.soundId,
2942
+ source_guild_id: options.sourceGuildId
2943
+ });
2944
+ }
2945
+ cachedMessages(channelId) {
2946
+ return this.#messageManagers.get(channelId);
2947
+ }
2138
2948
  async create(guildId, options) {
2139
2949
  return this.upsert(await this.#rest.post(Routes.guildChannels(guildId), options));
2140
2950
  }
@@ -2178,7 +2988,7 @@ class ChannelManager extends Manager {
2178
2988
  return this.messages(data.channel_id).upsert(data);
2179
2989
  }
2180
2990
  async editMessage(channelId, messageId, options) {
2181
- return this.messages(channelId).upsert(await this.#rest.patch(Routes.message(channelId, messageId), options));
2991
+ return this.messages(channelId).upsert(await this.#rest.patch(Routes.message(channelId, messageId), toRequest(options)));
2182
2992
  }
2183
2993
  async deleteMessage(channelId, messageId) {
2184
2994
  await this.#rest.delete(Routes.message(channelId, messageId));
@@ -2191,15 +3001,37 @@ class ChannelManager extends Manager {
2191
3001
  return this.messages(channelId).upsert(await this.#rest.post(Routes.crosspostMessage(channelId, messageId)));
2192
3002
  }
2193
3003
  async bulkDeleteMessages(channelId, messageIds) {
2194
- const ids = [...messageIds];
2195
- if (ids.length < 2 || ids.length > 100)
2196
- throw new RangeError("bulkDelete requires between 2 and 100 message IDs.");
3004
+ const ids = [...new Set(messageIds)];
3005
+ if (ids.length < 1 || ids.length > 100)
3006
+ throw new RangeError("bulkDelete requires between 1 and 100 message IDs.");
3007
+ if (ids.length === 1)
3008
+ return this.deleteMessage(channelId, ids[0]);
3009
+ const cutoff = Date.now() - BULK_DELETE_MAX_AGE_MS;
3010
+ const tooOld = ids.filter((id) => snowflakeTime(id) < cutoff);
3011
+ if (tooOld.length)
3012
+ throw new RangeError(`bulkDelete cannot delete messages older than 14 days: ${tooOld.join(", ")}`);
2197
3013
  await this.#rest.post(Routes.channelBulkDelete(channelId), {
2198
3014
  messages: ids
2199
3015
  });
2200
3016
  for (const id of ids)
2201
3017
  this.messages(channelId).delete(id);
2202
3018
  }
3019
+ async* iterateMessages(channelId, options = {}) {
3020
+ let before = options.before;
3021
+ let remaining = options.limit ?? Infinity;
3022
+ while (remaining > 0) {
3023
+ const page = await this.fetchMessages(channelId, {
3024
+ before,
3025
+ limit: Math.min(100, remaining)
3026
+ });
3027
+ for (const message of page)
3028
+ yield message;
3029
+ remaining -= page.length;
3030
+ if (page.length < 100)
3031
+ return;
3032
+ before = page.at(-1).id;
3033
+ }
3034
+ }
2203
3035
  async addReaction(channelId, messageId, emoji) {
2204
3036
  await this.#rest.put(`${Routes.messageReactions(channelId, messageId, emoji)}/@me`);
2205
3037
  }
@@ -2269,14 +3101,18 @@ export {
2269
3101
  GuildManager,
2270
3102
  GuildMemberManager,
2271
3103
  GuildScheduledEventManager,
3104
+ GuildSoundboardManager,
3105
+ GuildStickerManager,
2272
3106
  Manager,
2273
3107
  MessageManager,
3108
+ MonetizationManager,
2274
3109
  PermissionOverwriteManager,
2275
3110
  ResourceManager,
2276
3111
  RoleManager,
2277
3112
  StageInstanceManager,
2278
3113
  ThreadManager,
2279
- UserManager
3114
+ UserManager,
3115
+ toRequest
2280
3116
  };
2281
3117
 
2282
- //# debugId=E5CAD3E6B2BD672164756E2164756E21
3118
+ //# debugId=6C6CF1CF95B4E3CA64756E2164756E21