lunibee 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +225 -223
  3. package/dist/builders/commands.d.ts +6 -4
  4. package/dist/builders/components.d.ts +23 -0
  5. package/dist/builders/index.d.ts +2 -2
  6. package/dist/builders/index.js +120 -24
  7. package/dist/builders/index.js.map +9 -8
  8. package/dist/collection/index.d.ts +68 -1
  9. package/dist/collection/index.js +335 -1
  10. package/dist/collection/index.js.map +4 -4
  11. package/dist/core/collector.d.ts +13 -0
  12. package/dist/core/events.d.ts +112 -2
  13. package/dist/core/index.d.ts +30 -93
  14. package/dist/core/index.js +3386 -957
  15. package/dist/core/index.js.map +48 -24
  16. package/dist/core/permissions.d.ts +48 -0
  17. package/dist/formatters/index.js.map +1 -1
  18. package/dist/handlers/index.js.map +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.js +3806 -1193
  21. package/dist/index.js.map +64 -43
  22. package/dist/managers/advanced.d.ts +116 -0
  23. package/dist/managers/base.d.ts +13 -2
  24. package/dist/managers/emoji.d.ts +1 -1
  25. package/dist/managers/guild-resources.d.ts +109 -0
  26. package/dist/managers/guild.d.ts +33 -2
  27. package/dist/managers/index.d.ts +44 -6
  28. package/dist/managers/index.js +1186 -150
  29. package/dist/managers/index.js.map +27 -21
  30. package/dist/managers/message.d.ts +10 -1
  31. package/dist/rest/decoder.d.ts +23 -0
  32. package/dist/rest/errors.d.ts +53 -0
  33. package/dist/rest/index.d.ts +21 -17
  34. package/dist/rest/index.js +526 -264
  35. package/dist/rest/index.js.map +14 -8
  36. package/dist/rest/limiter.d.ts +42 -0
  37. package/dist/rest/redis.d.ts +18 -1
  38. package/dist/rest/route.d.ts +31 -0
  39. package/dist/rest/routes.d.ts +22 -0
  40. package/dist/rest/scheduler.d.ts +42 -0
  41. package/dist/rest/store.d.ts +29 -0
  42. package/dist/rest/transport.d.ts +40 -0
  43. package/dist/sharding/bus.d.ts +31 -0
  44. package/dist/sharding/cluster.d.ts +10 -0
  45. package/dist/sharding/index.d.ts +39 -2
  46. package/dist/sharding/index.js +1105 -404
  47. package/dist/sharding/index.js.map +18 -8
  48. package/dist/structures/base.d.ts +10 -0
  49. package/dist/structures/channels.d.ts +56 -0
  50. package/dist/structures/index.d.ts +1 -0
  51. package/dist/structures/index.js +305 -311
  52. package/dist/structures/index.js.map +18 -14
  53. package/dist/structures/interactions.d.ts +38 -52
  54. package/dist/structures/options.d.ts +55 -0
  55. package/dist/structures/resources.d.ts +3 -3
  56. package/dist/types/gateway-events.d.ts +132 -0
  57. package/dist/types/gateway.d.ts +197 -0
  58. package/dist/types/index.d.ts +53 -260
  59. package/dist/types/index.js +44 -2
  60. package/dist/types/index.js.map +5 -4
  61. package/dist/utils/index.js.map +1 -1
  62. package/dist/voice/index.d.ts +32 -1
  63. package/dist/voice/index.js +73 -7
  64. package/dist/voice/index.js.map +3 -3
  65. package/dist/ws/close-codes.d.ts +23 -0
  66. package/dist/ws/decoder.d.ts +58 -0
  67. package/dist/ws/heartbeat.d.ts +87 -0
  68. package/dist/ws/index.d.ts +18 -65
  69. package/dist/ws/index.js +911 -385
  70. package/dist/ws/index.js.map +15 -5
  71. package/dist/ws/opcodes.d.ts +14 -0
  72. package/dist/ws/protocol.d.ts +110 -0
  73. package/dist/ws/reconnect.d.ts +108 -0
  74. package/dist/ws/send-budget.d.ts +17 -0
  75. package/dist/ws/session.d.ts +100 -0
  76. package/dist/ws/state.d.ts +27 -0
  77. package/dist/ws/transport.d.ts +80 -0
  78. package/package.json +21 -20
@@ -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.7",
654
+ version: "0.2.0",
289
655
  type: "module",
290
656
  module: "./src/index.ts",
291
657
  types: "./src/index.ts",
@@ -335,6 +701,8 @@ var Routes = {
335
701
  threadMembers: (threadId) => `/channels/${snowflake(threadId, "Thread ID")}/thread-members`,
336
702
  guildScheduledEvents: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/scheduled-events`,
337
703
  guildScheduledEvent: (guildId, eventId) => `/guilds/${snowflake(guildId, "Guild ID")}/scheduled-events/${snowflake(eventId, "Event ID")}`,
704
+ guildScheduledEventUsers: (guildId, eventId) => `/guilds/${snowflake(guildId, "Guild ID")}/scheduled-events/${snowflake(eventId, "Event ID")}/users`,
705
+ channelPermission: (channelId, overwriteId) => `/channels/${snowflake(channelId, "Channel ID")}/permissions/${snowflake(overwriteId, "Overwrite ID")}`,
338
706
  guildAutoModerationRules: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/auto-moderation/rules`,
339
707
  guildAutoModerationRule: (guildId, ruleId) => `/guilds/${snowflake(guildId, "Guild ID")}/auto-moderation/rules/${snowflake(ruleId, "Rule ID")}`,
340
708
  voiceRegions: () => "/voice/regions",
@@ -350,13 +718,29 @@ var Routes = {
350
718
  invite: (code) => `/invites/${encodeURIComponent(code)}`,
351
719
  guildVanity: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/vanity-url`,
352
720
  guildEmoji: (guildId, emojiId) => emojiId ? `/guilds/${snowflake(guildId, "Guild ID")}/emojis/${snowflake(emojiId, "Emoji ID")}` : `/guilds/${snowflake(guildId, "Guild ID")}/emojis`,
353
- 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`
354
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
+ }
355
738
  function snowflake(value, field) {
356
739
  if (!/^\d{1,20}$/.test(value))
357
740
  throw new TypeError(`${field} must be a valid Discord snowflake.`);
358
741
  return value;
359
742
  }
743
+
360
744
  // packages/rest/src/index.ts
361
745
  var LIBRARY_VERSION = package_default.version;
362
746
  var LIBRARY_URL = "https://github.com/Ekretos/lunibee";
@@ -443,6 +827,7 @@ class Channel extends BaseStructure {
443
827
  nsfw;
444
828
  rateLimitPerUser;
445
829
  position;
830
+ permissionOverwrites;
446
831
  #context;
447
832
  constructor(data, context) {
448
833
  super(data.id);
@@ -456,6 +841,7 @@ class Channel extends BaseStructure {
456
841
  this.nsfw = data.nsfw;
457
842
  this.rateLimitPerUser = data.rate_limit_per_user;
458
843
  this.position = data.position;
844
+ this.permissionOverwrites = (data.permission_overwrites ?? []).map((overwrite) => ({ ...overwrite }));
459
845
  this.#context = context;
460
846
  }
461
847
  sendMessage(options) {
@@ -490,6 +876,18 @@ class Channel extends BaseStructure {
490
876
  update(options) {
491
877
  return this.edit(options);
492
878
  }
879
+ isThread() {
880
+ return this.type === 10 || this.type === 11 || this.type === 12;
881
+ }
882
+ isTextBased() {
883
+ return [0, 1, 2, 3, 5, 10, 11, 12, 13].includes(this.type);
884
+ }
885
+ isVoiceBased() {
886
+ return this.type === 2 || this.type === 13;
887
+ }
888
+ isDMBased() {
889
+ return this.type === 1 || this.type === 3;
890
+ }
493
891
  toString() {
494
892
  return `<#${this.id}>`;
495
893
  }
@@ -650,8 +1048,11 @@ var Permission = {
650
1048
  createEvents: 1n << 44n,
651
1049
  useExternalSounds: 1n << 45n,
652
1050
  sendVoiceMessages: 1n << 46n,
1051
+ setVoiceChannelStatus: 1n << 48n,
653
1052
  sendPolls: 1n << 49n,
654
- useExternalApps: 1n << 50n
1053
+ useExternalApps: 1n << 50n,
1054
+ pinMessages: 1n << 51n,
1055
+ bypassSlowmode: 1n << 52n
655
1056
  };
656
1057
  var Permissions = {
657
1058
  CreateInstantInvite: 1n << 0n,
@@ -701,8 +1102,11 @@ var Permissions = {
701
1102
  CreateEvents: 1n << 44n,
702
1103
  UseExternalSounds: 1n << 45n,
703
1104
  SendVoiceMessages: 1n << 46n,
1105
+ SetVoiceChannelStatus: 1n << 48n,
704
1106
  SendPolls: 1n << 49n,
705
- UseExternalApps: 1n << 50n
1107
+ UseExternalApps: 1n << 50n,
1108
+ PinMessages: 1n << 51n,
1109
+ BypassSlowmode: 1n << 52n
706
1110
  };
707
1111
  var PermissionFlagsBits = {
708
1112
  CreateInstantInvite: 1n << 0n,
@@ -752,8 +1156,11 @@ var PermissionFlagsBits = {
752
1156
  CreateEvents: 1n << 44n,
753
1157
  UseExternalSounds: 1n << 45n,
754
1158
  SendVoiceMessages: 1n << 46n,
1159
+ SetVoiceChannelStatus: 1n << 48n,
755
1160
  SendPolls: 1n << 49n,
756
- UseExternalApps: 1n << 50n
1161
+ UseExternalApps: 1n << 50n,
1162
+ PinMessages: 1n << 51n,
1163
+ BypassSlowmode: 1n << 52n
757
1164
  };
758
1165
 
759
1166
  class PermissionSet {
@@ -955,6 +1362,10 @@ class PermissionSet {
955
1362
  }
956
1363
  return false;
957
1364
  }
1365
+ missing(...permissions) {
1366
+ const wanted = new PermissionSet(permissions);
1367
+ return wanted.toArray().filter((name) => !this.has(name));
1368
+ }
958
1369
  add(...permissions) {
959
1370
  let bitfield = this.bitfield;
960
1371
  for (let i = 0;i < permissions.length; i++) {
@@ -1016,7 +1427,8 @@ class PermissionsBitField extends PermissionSet {
1016
1427
  super(value);
1017
1428
  }
1018
1429
  }
1019
- // packages/types/src/index.ts
1430
+ var ALL_PERMISSIONS = Object.values(Permission).reduce((bits, bit) => bits | bit, 0n);
1431
+ // packages/types/src/gateway.ts
1020
1432
  var GatewayIntentBits = {
1021
1433
  Guilds: 1 << 0,
1022
1434
  GuildMembers: 1 << 1,
@@ -1068,6 +1480,37 @@ var IntentBits = {
1068
1480
  guildMessagePolls: 1 << 24,
1069
1481
  directMessagePolls: 1 << 25
1070
1482
  };
1483
+ // packages/ws/src/close-codes.ts
1484
+ var GatewayCloseCodes = {
1485
+ UnknownError: 4000,
1486
+ UnknownOpcode: 4001,
1487
+ DecodeError: 4002,
1488
+ NotAuthenticated: 4003,
1489
+ AuthenticationFailed: 4004,
1490
+ AlreadyAuthenticated: 4005,
1491
+ InvalidSeq: 4007,
1492
+ RateLimited: 4008,
1493
+ SessionTimedOut: 4009,
1494
+ InvalidShard: 4010,
1495
+ ShardingRequired: 4011,
1496
+ InvalidAPIVersion: 4012,
1497
+ InvalidIntents: 4013,
1498
+ DisallowedIntents: 4014
1499
+ };
1500
+
1501
+ // packages/ws/src/reconnect.ts
1502
+ var FATAL_CLOSE_CODES = [
1503
+ GatewayCloseCodes.AuthenticationFailed,
1504
+ GatewayCloseCodes.InvalidShard,
1505
+ GatewayCloseCodes.ShardingRequired,
1506
+ GatewayCloseCodes.InvalidAPIVersion,
1507
+ GatewayCloseCodes.InvalidIntents,
1508
+ GatewayCloseCodes.DisallowedIntents
1509
+ ];
1510
+ var IDENTIFY_CLOSE_CODES = [
1511
+ GatewayCloseCodes.InvalidSeq,
1512
+ GatewayCloseCodes.SessionTimedOut
1513
+ ];
1071
1514
  // packages/structures/src/resources.ts
1072
1515
  function toDateOrNull(value) {
1073
1516
  if (!value)
@@ -1165,6 +1608,15 @@ class Role extends BaseStructure {
1165
1608
  return `<@&${this.id}>`;
1166
1609
  }
1167
1610
  }
1611
+
1612
+ class TextChannel extends Channel {
1613
+ constructor(data, context) {
1614
+ super(data, context);
1615
+ }
1616
+ toString() {
1617
+ return `<#${this.id}>`;
1618
+ }
1619
+ }
1168
1620
  class Emoji extends BaseStructure {
1169
1621
  name;
1170
1622
  roleIds;
@@ -1174,7 +1626,9 @@ class Emoji extends BaseStructure {
1174
1626
  animated;
1175
1627
  available;
1176
1628
  constructor(data) {
1177
- super(data.id ?? "unicode");
1629
+ super(data.id ?? "0");
1630
+ if (data.id === null)
1631
+ this.id = "unicode";
1178
1632
  this.name = data.name;
1179
1633
  this.roleIds = data.roles ?? [];
1180
1634
  this.user = data.user ? new User(data.user) : null;
@@ -1237,6 +1691,109 @@ class AutoModerationRule extends BaseStructure {
1237
1691
  };
1238
1692
  }
1239
1693
  }
1694
+ // packages/structures/src/channels.ts
1695
+ class NewsChannel extends TextChannel {
1696
+ }
1697
+
1698
+ class DMChannel extends Channel {
1699
+ recipients;
1700
+ ownerId;
1701
+ constructor(data, context) {
1702
+ super(data, context);
1703
+ this.recipients = (data.recipients ?? []).map((u) => new User(u));
1704
+ this.ownerId = data.owner_id ?? null;
1705
+ }
1706
+ }
1707
+
1708
+ class VoiceChannel extends Channel {
1709
+ bitrate;
1710
+ userLimit;
1711
+ rtcRegion;
1712
+ videoQualityMode;
1713
+ constructor(data, context) {
1714
+ super(data, context);
1715
+ this.bitrate = data.bitrate ?? 64000;
1716
+ this.userLimit = data.user_limit ?? 0;
1717
+ this.rtcRegion = data.rtc_region ?? null;
1718
+ this.videoQualityMode = data.video_quality_mode ?? 1;
1719
+ }
1720
+ }
1721
+
1722
+ class StageChannel extends VoiceChannel {
1723
+ }
1724
+
1725
+ class CategoryChannel extends Channel {
1726
+ }
1727
+
1728
+ class ThreadChannel extends Channel {
1729
+ ownerId;
1730
+ messageCount;
1731
+ memberCount;
1732
+ metadata;
1733
+ constructor(data, context) {
1734
+ super(data, context);
1735
+ this.ownerId = data.owner_id ?? null;
1736
+ this.messageCount = data.message_count ?? 0;
1737
+ this.memberCount = data.member_count ?? 0;
1738
+ this.metadata = data.thread_metadata ?? null;
1739
+ }
1740
+ get archived() {
1741
+ return this.metadata?.archived ?? false;
1742
+ }
1743
+ get locked() {
1744
+ return this.metadata?.locked ?? false;
1745
+ }
1746
+ get autoArchiveDuration() {
1747
+ return this.metadata?.auto_archive_duration ?? null;
1748
+ }
1749
+ }
1750
+
1751
+ class ForumChannel extends Channel {
1752
+ availableTags;
1753
+ defaultReactionEmoji;
1754
+ defaultThreadRateLimitPerUser;
1755
+ defaultAutoArchiveDuration;
1756
+ constructor(data, context) {
1757
+ super(data, context);
1758
+ this.availableTags = data.available_tags ?? [];
1759
+ this.defaultReactionEmoji = data.default_reaction_emoji ?? null;
1760
+ this.defaultThreadRateLimitPerUser = data.default_thread_rate_limit_per_user ?? 0;
1761
+ this.defaultAutoArchiveDuration = data.default_auto_archive_duration ?? null;
1762
+ }
1763
+ }
1764
+
1765
+ class MediaChannel extends ForumChannel {
1766
+ }
1767
+ function createChannel2(data, context) {
1768
+ switch (data.type) {
1769
+ case 0:
1770
+ return new TextChannel(data, context);
1771
+ case 1:
1772
+ case 3:
1773
+ return new DMChannel(data, context);
1774
+ case 2:
1775
+ return new VoiceChannel(data, context);
1776
+ case 4:
1777
+ return new CategoryChannel(data, context);
1778
+ case 5:
1779
+ return new NewsChannel(data, context);
1780
+ case 10:
1781
+ case 11:
1782
+ case 12:
1783
+ return new ThreadChannel(data, context);
1784
+ case 13:
1785
+ return new StageChannel(data, context);
1786
+ case 15:
1787
+ return new ForumChannel(data, context);
1788
+ case 16:
1789
+ return new MediaChannel(data, context);
1790
+ default:
1791
+ return new Channel(data, context);
1792
+ }
1793
+ }
1794
+ // packages/structures/src/interactions.ts
1795
+ var TOKEN_LIFETIME_MS = 15 * 60000;
1796
+
1240
1797
  // packages/structures/src/index.ts
1241
1798
  var NON_SYSTEM_MESSAGE_TYPES = new Set([0, 19, 20, 23]);
1242
1799
 
@@ -1394,16 +1951,22 @@ class Message extends BaseStructure {
1394
1951
 
1395
1952
  // packages/managers/src/message.ts
1396
1953
  class MessageManager {
1397
- cache = new Collection;
1954
+ cache;
1955
+ #caching;
1398
1956
  #rest;
1399
1957
  #context;
1400
1958
  #channelId;
1401
- constructor(rest, context, channelId) {
1959
+ constructor(rest, context, channelId, cache) {
1402
1960
  if (!channelId)
1403
1961
  throw new TypeError("Channel ID is required.");
1404
1962
  this.#rest = rest;
1405
1963
  this.#context = context;
1406
1964
  this.#channelId = channelId;
1965
+ this.#caching = cache !== undefined;
1966
+ this.cache = new Collection(null, {
1967
+ ttl: cache?.ttl,
1968
+ maxSize: cache ? cache.maxSize ?? 100 : undefined
1969
+ });
1407
1970
  }
1408
1971
  async resolve(messageId) {
1409
1972
  return this.cache.get(messageId) ?? this.fetch(messageId);
@@ -1420,13 +1983,14 @@ class MessageManager {
1420
1983
  return Promise.all(Array.from(messageIds, (messageId) => this.fetch(messageId)));
1421
1984
  }
1422
1985
  upsert(data) {
1423
- const existing = this.cache.get(data.id);
1986
+ const existing = this.cache.peek(data.id);
1424
1987
  const message = new Message(data, this.#context);
1425
1988
  if (existing) {
1426
1989
  Object.assign(existing, message);
1427
1990
  return existing;
1428
1991
  }
1429
- this.cache.set(message.id, message);
1992
+ if (this.#caching)
1993
+ this.cache.set(message.id, message);
1430
1994
  return message;
1431
1995
  }
1432
1996
  delete(messageId) {
@@ -1452,7 +2016,7 @@ class ThreadManager {
1452
2016
  auto_archive_duration: options.autoArchiveDuration,
1453
2017
  rate_limit_per_user: options.rateLimitPerUser
1454
2018
  });
1455
- return new Channel(data, this.#context);
2019
+ return createChannel2(data, this.#context);
1456
2020
  }
1457
2021
  }
1458
2022
 
@@ -1480,18 +2044,536 @@ class UserManager extends ResourceManager {
1480
2044
  });
1481
2045
  }
1482
2046
  }
2047
+ // packages/managers/src/emoji.ts
2048
+ class EmojiManager extends Manager {
2049
+ #rest;
2050
+ #guildId;
2051
+ constructor(rest, guildId) {
2052
+ super();
2053
+ this.#rest = rest;
2054
+ this.#guildId = guildId;
2055
+ }
2056
+ fetch(emojiId) {
2057
+ return this.fetchOnce(emojiId, async () => new Emoji(await this.#rest.get(Routes.guildEmoji(this.#guildId, emojiId))), (emoji) => this.#merge(emojiId, emoji));
2058
+ }
2059
+ async fetchAll() {
2060
+ const data = await this.#rest.get(Routes.guildEmoji(this.#guildId));
2061
+ return data.map((item) => this.upsert(item));
2062
+ }
2063
+ async create(options) {
2064
+ return this.upsert(await this.#rest.post(Routes.guildEmoji(this.#guildId), options));
2065
+ }
2066
+ async edit(emojiId, options) {
2067
+ return this.upsert(await this.#rest.patch(Routes.guildEmoji(this.#guildId, emojiId), options));
2068
+ }
2069
+ async deleteEmoji(emojiId) {
2070
+ await this.#rest.delete(Routes.guildEmoji(this.#guildId, emojiId));
2071
+ this.delete(emojiId);
2072
+ }
2073
+ upsert(data) {
2074
+ const key = data.id != null ? data.id : `unicode:${data.name ?? ""}`;
2075
+ return this.#merge(key, new Emoji(data));
2076
+ }
2077
+ #merge(key, emoji) {
2078
+ const existing = this.get(key);
2079
+ if (existing) {
2080
+ Object.assign(existing, emoji);
2081
+ return existing;
2082
+ }
2083
+ this.set(key, emoji);
2084
+ return emoji;
2085
+ }
2086
+ }
2087
+
2088
+ // packages/managers/src/advanced.ts
2089
+ function withQuery(path, query) {
2090
+ const params = new URLSearchParams;
2091
+ for (const [key, value] of Object.entries(query))
2092
+ if (value !== undefined)
2093
+ params.set(key, String(value));
2094
+ const suffix = params.toString();
2095
+ return suffix ? `${path}?${suffix}` : path;
2096
+ }
2097
+
2098
+ class GuildStickerManager extends Manager {
2099
+ #rest;
2100
+ guildId;
2101
+ constructor(rest, guildId) {
2102
+ super();
2103
+ this.#rest = rest;
2104
+ this.guildId = guildId;
2105
+ }
2106
+ #store(sticker) {
2107
+ this.set(sticker.id, sticker);
2108
+ return sticker;
2109
+ }
2110
+ async fetchAll() {
2111
+ const stickers = await this.#rest.get(Routes.guildSticker(this.guildId));
2112
+ this.clear();
2113
+ return stickers.map((sticker) => this.#store(sticker));
2114
+ }
2115
+ async fetch(stickerId) {
2116
+ return this.#store(await this.#rest.get(Routes.guildSticker(this.guildId, stickerId)));
2117
+ }
2118
+ async create(options) {
2119
+ const form = new FormData;
2120
+ form.set("name", options.name);
2121
+ form.set("description", options.description);
2122
+ form.set("tags", options.tags);
2123
+ form.set("file", options.file);
2124
+ return this.#store(await this.#rest.post(Routes.guildSticker(this.guildId), form, { reason: options.reason }));
2125
+ }
2126
+ async edit(stickerId, options) {
2127
+ const { reason, ...body } = options;
2128
+ return this.#store(await this.#rest.patch(Routes.guildSticker(this.guildId, stickerId), body, { reason }));
2129
+ }
2130
+ async remove(stickerId, reason) {
2131
+ await this.#rest.delete(Routes.guildSticker(this.guildId, stickerId), {
2132
+ reason
2133
+ });
2134
+ this.delete(stickerId);
2135
+ }
2136
+ sync(stickers) {
2137
+ this.clear();
2138
+ for (const sticker of stickers)
2139
+ this.#store(sticker);
2140
+ }
2141
+ }
2142
+
2143
+ class GuildSoundboardManager extends Manager {
2144
+ #rest;
2145
+ guildId;
2146
+ constructor(rest, guildId) {
2147
+ super();
2148
+ this.#rest = rest;
2149
+ this.guildId = guildId;
2150
+ }
2151
+ #store(sound) {
2152
+ this.set(sound.sound_id, sound);
2153
+ return sound;
2154
+ }
2155
+ async fetchAll() {
2156
+ const { items } = await this.#rest.get(Routes.guildSoundboardSound(this.guildId));
2157
+ this.clear();
2158
+ return items.map((sound) => this.#store(sound));
2159
+ }
2160
+ async fetch(soundId) {
2161
+ return this.#store(await this.#rest.get(Routes.guildSoundboardSound(this.guildId, soundId)));
2162
+ }
2163
+ async create(options) {
2164
+ if (options.volume !== undefined && (options.volume < 0 || options.volume > 1))
2165
+ throw new RangeError("Soundboard volume must be between 0 and 1.");
2166
+ return this.#store(await this.#rest.post(Routes.guildSoundboardSound(this.guildId), {
2167
+ name: options.name,
2168
+ sound: options.sound,
2169
+ volume: options.volume,
2170
+ emoji_id: options.emojiId,
2171
+ emoji_name: options.emojiName
2172
+ }, { reason: options.reason }));
2173
+ }
2174
+ async edit(soundId, options) {
2175
+ return this.#store(await this.#rest.patch(Routes.guildSoundboardSound(this.guildId, soundId), {
2176
+ name: options.name,
2177
+ volume: options.volume,
2178
+ emoji_id: options.emojiId,
2179
+ emoji_name: options.emojiName
2180
+ }, { reason: options.reason }));
2181
+ }
2182
+ async remove(soundId, reason) {
2183
+ await this.#rest.delete(Routes.guildSoundboardSound(this.guildId, soundId), { reason });
2184
+ this.delete(soundId);
2185
+ }
2186
+ }
2187
+
2188
+ class MonetizationManager extends Manager {
2189
+ #rest;
2190
+ applicationId;
2191
+ constructor(rest, applicationId) {
2192
+ super();
2193
+ this.#rest = rest;
2194
+ this.applicationId = applicationId;
2195
+ }
2196
+ fetchSkus() {
2197
+ return this.#rest.get(Routes.applicationSkus(this.applicationId));
2198
+ }
2199
+ async fetchEntitlements(query = {}) {
2200
+ if (query.limit !== undefined && (!Number.isInteger(query.limit) || query.limit < 1 || query.limit > 100))
2201
+ throw new RangeError("Entitlement limit must be 1-100.");
2202
+ const entitlements = await this.#rest.get(withQuery(Routes.applicationEntitlement(this.applicationId), {
2203
+ user_id: query.userId,
2204
+ sku_ids: query.skuIds?.join(","),
2205
+ guild_id: query.guildId,
2206
+ before: query.before,
2207
+ after: query.after,
2208
+ limit: query.limit,
2209
+ exclude_ended: query.excludeEnded,
2210
+ exclude_deleted: query.excludeDeleted
2211
+ }));
2212
+ for (const entitlement of entitlements)
2213
+ this.set(entitlement.id, entitlement);
2214
+ return entitlements;
2215
+ }
2216
+ async fetch(entitlementId) {
2217
+ const entitlement = await this.#rest.get(Routes.applicationEntitlement(this.applicationId, entitlementId));
2218
+ this.set(entitlement.id, entitlement);
2219
+ return entitlement;
2220
+ }
2221
+ async consume(entitlementId) {
2222
+ await this.#rest.post(Routes.consumeEntitlement(this.applicationId, entitlementId));
2223
+ const cached = this.get(entitlementId);
2224
+ if (cached)
2225
+ cached.consumed = true;
2226
+ }
2227
+ async createTestEntitlement(options) {
2228
+ const entitlement = await this.#rest.post(Routes.applicationEntitlement(this.applicationId), {
2229
+ sku_id: options.skuId,
2230
+ owner_id: options.ownerId,
2231
+ owner_type: options.ownerType
2232
+ });
2233
+ this.set(entitlement.id, entitlement);
2234
+ return entitlement;
2235
+ }
2236
+ async deleteTestEntitlement(entitlementId) {
2237
+ await this.#rest.delete(Routes.applicationEntitlement(this.applicationId, entitlementId));
2238
+ this.delete(entitlementId);
2239
+ }
2240
+ fetchSubscriptions(skuId, query = {}) {
2241
+ return this.#rest.get(withQuery(Routes.skuSubscription(skuId), {
2242
+ user_id: query.userId,
2243
+ before: query.before,
2244
+ after: query.after,
2245
+ limit: query.limit
2246
+ }));
2247
+ }
2248
+ fetchSubscription(skuId, subscriptionId) {
2249
+ return this.#rest.get(Routes.skuSubscription(skuId, subscriptionId));
2250
+ }
2251
+ }
2252
+
2253
+ // packages/managers/src/member.ts
2254
+ class GuildMemberManager extends ResourceManager {
2255
+ #rest;
2256
+ guildId;
2257
+ constructor(guildId, rest) {
2258
+ super((id) => rest.get(Routes.guildMember(guildId, id)).then((data) => new GuildMember({ ...data, guild_id: guildId })), (member) => member.user.id);
2259
+ this.guildId = guildId;
2260
+ this.#rest = rest;
2261
+ }
2262
+ async kick(userId) {
2263
+ await this.#rest.delete(Routes.guildMember(this.guildId, userId));
2264
+ this.delete(userId);
2265
+ }
2266
+ async ban(userId, options = {}) {
2267
+ await this.#rest.put(Routes.guildBan(this.guildId, userId), { delete_message_seconds: options.deleteMessageSeconds }, { reason: options.reason });
2268
+ this.delete(userId);
2269
+ }
2270
+ async unban(userId) {
2271
+ await this.#rest.delete(Routes.guildBan(this.guildId, userId));
2272
+ }
2273
+ async edit(userId, options) {
2274
+ const data = await this.#rest.patch(Routes.guildMember(this.guildId, userId), options);
2275
+ const member = new GuildMember({ ...data, guild_id: this.guildId });
2276
+ this.set(member.user.id, member);
2277
+ return member;
2278
+ }
2279
+ async addRole(userId, roleId) {
2280
+ await this.#rest.put(Routes.guildMemberRole(this.guildId, userId, roleId));
2281
+ }
2282
+ async removeRole(userId, roleId) {
2283
+ await this.#rest.delete(Routes.guildMemberRole(this.guildId, userId, roleId));
2284
+ }
2285
+ async timeout(userId, milliseconds) {
2286
+ const timeoutDate = milliseconds === null ? null : new Date(Date.now() + milliseconds).toISOString();
2287
+ return this.edit(userId, { communication_disabled_until: timeoutDate });
2288
+ }
2289
+ }
2290
+
2291
+ // packages/managers/src/role.ts
2292
+ class RoleManager extends ResourceManager {
2293
+ #rest;
2294
+ guildId;
2295
+ constructor(guildId, rest) {
2296
+ super((id) => rest.get(Routes.guildRole(guildId, id)).then((data) => new Role(data)), (role) => role.id);
2297
+ this.guildId = guildId;
2298
+ this.#rest = rest;
2299
+ }
2300
+ async fetchAll() {
2301
+ const data = await this.#rest.get(Routes.guildRoles(this.guildId));
2302
+ return data.map((item) => {
2303
+ const role = new Role(item);
2304
+ this.set(role.id, role);
2305
+ return role;
2306
+ });
2307
+ }
2308
+ async create(options) {
2309
+ const { reason, ...payload } = options;
2310
+ const data = await this.#rest.post(Routes.guildRoles(this.guildId), {
2311
+ ...payload,
2312
+ permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
2313
+ });
2314
+ const role = new Role(data);
2315
+ this.set(role.id, role);
2316
+ return role;
2317
+ }
2318
+ async edit(roleId, options) {
2319
+ const { reason, ...payload } = options;
2320
+ const data = await this.#rest.patch(Routes.guildRole(this.guildId, roleId), {
2321
+ ...payload,
2322
+ permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
2323
+ });
2324
+ const role = new Role(data);
2325
+ this.set(role.id, role);
2326
+ return role;
2327
+ }
2328
+ async deleteRole(roleId) {
2329
+ await this.#rest.delete(Routes.guildRole(this.guildId, roleId));
2330
+ this.delete(roleId);
2331
+ }
2332
+ }
2333
+
2334
+ // packages/managers/src/guild-resources.ts
2335
+ function withQuery2(path, params) {
2336
+ const query = new URLSearchParams;
2337
+ for (const [key, value] of Object.entries(params))
2338
+ if (value !== undefined)
2339
+ query.set(key, String(value));
2340
+ const suffix = query.toString();
2341
+ return suffix ? `${path}?${suffix}` : path;
2342
+ }
2343
+
2344
+ class GuildBanManager extends Manager {
2345
+ #rest;
2346
+ guildId;
2347
+ constructor(rest, guildId) {
2348
+ super();
2349
+ this.#rest = rest;
2350
+ this.guildId = guildId;
2351
+ }
2352
+ async fetch(userId) {
2353
+ const ban = await this.#rest.get(Routes.guildBan(this.guildId, userId));
2354
+ this.set(ban.user.id, ban);
2355
+ return ban;
2356
+ }
2357
+ async fetchAll(options = {}) {
2358
+ const limit = options.limit === undefined ? undefined : Math.min(1000, Math.max(1, options.limit));
2359
+ const bans = await this.#rest.get(withQuery2(Routes.guildBans(this.guildId), {
2360
+ limit,
2361
+ before: options.before,
2362
+ after: options.after
2363
+ }));
2364
+ for (const ban of bans)
2365
+ this.set(ban.user.id, ban);
2366
+ return bans;
2367
+ }
2368
+ async create(userId, options = {}) {
2369
+ await this.#rest.put(Routes.guildBan(this.guildId, userId), { delete_message_seconds: options.deleteMessageSeconds }, { reason: options.reason });
2370
+ }
2371
+ async remove(userId, reason) {
2372
+ await this.#rest.delete(Routes.guildBan(this.guildId, userId), {
2373
+ reason
2374
+ });
2375
+ this.delete(userId);
2376
+ }
2377
+ }
2378
+
2379
+ class GuildScheduledEventManager extends Manager {
2380
+ #rest;
2381
+ guildId;
2382
+ constructor(rest, guildId) {
2383
+ super();
2384
+ this.#rest = rest;
2385
+ this.guildId = guildId;
2386
+ }
2387
+ #store(event) {
2388
+ this.set(event.id, event);
2389
+ return event;
2390
+ }
2391
+ async fetch(eventId, options = {}) {
2392
+ return this.#store(await this.#rest.get(withQuery2(Routes.guildScheduledEvent(this.guildId, eventId), {
2393
+ with_user_count: options.withUserCount
2394
+ })));
2395
+ }
2396
+ async fetchAll(options = {}) {
2397
+ const events = await this.#rest.get(withQuery2(Routes.guildScheduledEvents(this.guildId), {
2398
+ with_user_count: options.withUserCount
2399
+ }));
2400
+ return events.map((event) => this.#store(event));
2401
+ }
2402
+ async create(options, reason) {
2403
+ return this.#store(await this.#rest.post(Routes.guildScheduledEvents(this.guildId), options, { reason }));
2404
+ }
2405
+ async edit(eventId, options, reason) {
2406
+ return this.#store(await this.#rest.patch(Routes.guildScheduledEvent(this.guildId, eventId), options, { reason }));
2407
+ }
2408
+ async remove(eventId) {
2409
+ await this.#rest.delete(Routes.guildScheduledEvent(this.guildId, eventId));
2410
+ this.delete(eventId);
2411
+ }
2412
+ async fetchSubscribers(eventId, options = {}) {
2413
+ const limit = options.limit === undefined ? undefined : Math.min(100, Math.max(1, options.limit));
2414
+ return this.#rest.get(withQuery2(Routes.guildScheduledEventUsers(this.guildId, eventId), {
2415
+ limit,
2416
+ with_member: options.withMember,
2417
+ before: options.before,
2418
+ after: options.after
2419
+ }));
2420
+ }
2421
+ }
2422
+
2423
+ class StageInstanceManager extends Manager {
2424
+ #rest;
2425
+ constructor(rest) {
2426
+ super();
2427
+ this.#rest = rest;
2428
+ }
2429
+ #store(stage) {
2430
+ this.set(stage.channel_id, stage);
2431
+ return stage;
2432
+ }
2433
+ async create(channelId, options, reason) {
2434
+ return this.#store(await this.#rest.post(Routes.stageInstances(), {
2435
+ channel_id: channelId,
2436
+ topic: options.topic,
2437
+ privacy_level: options.privacyLevel,
2438
+ send_start_notification: options.sendStartNotification,
2439
+ guild_scheduled_event_id: options.guildScheduledEventId
2440
+ }, { reason }));
2441
+ }
2442
+ async fetch(channelId) {
2443
+ return this.#store(await this.#rest.get(Routes.stageInstanceByChannel(channelId)));
2444
+ }
2445
+ async edit(channelId, options, reason) {
2446
+ return this.#store(await this.#rest.patch(Routes.stageInstanceByChannel(channelId), { topic: options.topic, privacy_level: options.privacyLevel }, { reason }));
2447
+ }
2448
+ async remove(channelId, reason) {
2449
+ await this.#rest.delete(Routes.stageInstanceByChannel(channelId), {
2450
+ reason
2451
+ });
2452
+ this.delete(channelId);
2453
+ }
2454
+ }
2455
+
2456
+ class PermissionOverwriteManager {
2457
+ #rest;
2458
+ channelId;
2459
+ constructor(rest, channelId) {
2460
+ this.#rest = rest;
2461
+ this.channelId = channelId;
2462
+ }
2463
+ async edit(overwriteId, options, reason) {
2464
+ await this.#rest.put(Routes.channelPermission(this.channelId, overwriteId), {
2465
+ type: options.type,
2466
+ allow: BigInt(options.allow ?? 0).toString(),
2467
+ deny: BigInt(options.deny ?? 0).toString()
2468
+ }, { reason });
2469
+ }
2470
+ async remove(overwriteId, reason) {
2471
+ await this.#rest.delete(Routes.channelPermission(this.channelId, overwriteId), { reason });
2472
+ }
2473
+ }
2474
+
1483
2475
  // packages/managers/src/guild.ts
1484
- function withQuery(path, params) {
2476
+ function withQuery3(path, params) {
1485
2477
  const suffix = params.toString();
1486
2478
  return suffix ? `${path}?${suffix}` : path;
1487
2479
  }
1488
2480
 
1489
2481
  class GuildManager extends ResourceManager {
1490
2482
  #rest;
2483
+ #bans = new Map;
2484
+ #scheduledEvents = new Map;
2485
+ #members = new Map;
2486
+ #roles = new Map;
2487
+ #emojis = new Map;
2488
+ #stickers = new Map;
2489
+ #soundboard = new Map;
2490
+ #voiceStates = new Map;
2491
+ #autoModerationRules = new Map;
2492
+ #invites = new Map;
2493
+ #perGuild(map, guildId, create) {
2494
+ let manager = map.get(guildId);
2495
+ if (!manager)
2496
+ map.set(guildId, manager = create());
2497
+ return manager;
2498
+ }
1491
2499
  constructor(rest) {
1492
2500
  super(async (id) => new Guild(await rest.get(Routes.guild(id))), (guild) => guild.id);
1493
2501
  this.#rest = rest;
1494
2502
  }
2503
+ bans(guildId) {
2504
+ let manager = this.#bans.get(guildId);
2505
+ if (!manager)
2506
+ this.#bans.set(guildId, manager = new GuildBanManager(this.#rest, guildId));
2507
+ return manager;
2508
+ }
2509
+ scheduledEvents(guildId) {
2510
+ let manager = this.#scheduledEvents.get(guildId);
2511
+ if (!manager)
2512
+ this.#scheduledEvents.set(guildId, manager = new GuildScheduledEventManager(this.#rest, guildId));
2513
+ return manager;
2514
+ }
2515
+ members(guildId) {
2516
+ let manager = this.#members.get(guildId);
2517
+ if (!manager)
2518
+ this.#members.set(guildId, manager = new GuildMemberManager(guildId, this.#rest));
2519
+ return manager;
2520
+ }
2521
+ roles(guildId) {
2522
+ let manager = this.#roles.get(guildId);
2523
+ if (!manager)
2524
+ this.#roles.set(guildId, manager = new RoleManager(guildId, this.#rest));
2525
+ return manager;
2526
+ }
2527
+ emojis(guildId) {
2528
+ let manager = this.#emojis.get(guildId);
2529
+ if (!manager)
2530
+ this.#emojis.set(guildId, manager = new EmojiManager(this.#rest, guildId));
2531
+ return manager;
2532
+ }
2533
+ stickers(guildId) {
2534
+ let manager = this.#stickers.get(guildId);
2535
+ if (!manager)
2536
+ this.#stickers.set(guildId, manager = new GuildStickerManager(this.#rest, guildId));
2537
+ return manager;
2538
+ }
2539
+ soundboard(guildId) {
2540
+ let manager = this.#soundboard.get(guildId);
2541
+ if (!manager)
2542
+ this.#soundboard.set(guildId, manager = new GuildSoundboardManager(this.#rest, guildId));
2543
+ return manager;
2544
+ }
2545
+ voiceStates(guildId) {
2546
+ return this.#perGuild(this.#voiceStates, guildId, () => new Manager);
2547
+ }
2548
+ autoModerationRules(guildId) {
2549
+ return this.#perGuild(this.#autoModerationRules, guildId, () => new Manager);
2550
+ }
2551
+ invites(guildId) {
2552
+ return this.#perGuild(this.#invites, guildId, () => new Manager);
2553
+ }
2554
+ patch(data) {
2555
+ const guild = new Guild(data);
2556
+ const existing = this.get(guild.id);
2557
+ if (!existing)
2558
+ return this.upsert(guild);
2559
+ for (const [key, value] of Object.entries(guild))
2560
+ if (value !== undefined)
2561
+ existing[key] = value;
2562
+ return existing;
2563
+ }
2564
+ delete(id) {
2565
+ this.#bans.delete(id);
2566
+ this.#scheduledEvents.delete(id);
2567
+ this.#members.delete(id);
2568
+ this.#roles.delete(id);
2569
+ this.#emojis.delete(id);
2570
+ this.#stickers.delete(id);
2571
+ this.#soundboard.delete(id);
2572
+ this.#voiceStates.delete(id);
2573
+ this.#autoModerationRules.delete(id);
2574
+ this.#invites.delete(id);
2575
+ return super.delete(id);
2576
+ }
1495
2577
  async create(options) {
1496
2578
  const data = await this.#rest.post("/guilds", options);
1497
2579
  return this.upsert(new Guild(data));
@@ -1527,7 +2609,7 @@ class GuildManager extends ResourceManager {
1527
2609
  params.set("after", options.after);
1528
2610
  if (options.limit !== undefined)
1529
2611
  params.set("limit", String(Math.min(100, Math.max(1, options.limit))));
1530
- return this.#rest.get(withQuery(Routes.guildAuditLog(guildId), params));
2612
+ return this.#rest.get(withQuery3(Routes.guildAuditLog(guildId), params));
1531
2613
  }
1532
2614
  async fetchMembers(guildId, options = {}) {
1533
2615
  const params = new URLSearchParams;
@@ -1535,7 +2617,7 @@ class GuildManager extends ResourceManager {
1535
2617
  params.set("limit", String(Math.min(1000, Math.max(1, options.limit))));
1536
2618
  if (options.after)
1537
2619
  params.set("after", options.after);
1538
- return this.#rest.get(withQuery(Routes.guildMembers(guildId), params));
2620
+ return this.#rest.get(withQuery3(Routes.guildMembers(guildId), params));
1539
2621
  }
1540
2622
  async fetchAutoModerationRules(guildId) {
1541
2623
  const rules = await this.#rest.get(Routes.guildAutoModerationRules(guildId));
@@ -1610,87 +2692,6 @@ var AuditLogEvent = {
1610
2692
  AutoModerationRuleDelete: 142,
1611
2693
  AutoModerationBlockMessage: 143
1612
2694
  };
1613
- // packages/managers/src/role.ts
1614
- class RoleManager extends ResourceManager {
1615
- #rest;
1616
- guildId;
1617
- constructor(guildId, rest) {
1618
- super((id) => rest.get(Routes.guildRole(guildId, id)).then((data) => new Role(data)), (role) => role.id);
1619
- this.guildId = guildId;
1620
- this.#rest = rest;
1621
- }
1622
- async fetchAll() {
1623
- const data = await this.#rest.get(Routes.guildRoles(this.guildId));
1624
- return data.map((item) => {
1625
- const role = new Role(item);
1626
- this.set(role.id, role);
1627
- return role;
1628
- });
1629
- }
1630
- async create(options) {
1631
- const { reason, ...payload } = options;
1632
- const data = await this.#rest.post(Routes.guildRoles(this.guildId), {
1633
- ...payload,
1634
- permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
1635
- });
1636
- const role = new Role(data);
1637
- this.set(role.id, role);
1638
- return role;
1639
- }
1640
- async edit(roleId, options) {
1641
- const { reason, ...payload } = options;
1642
- const data = await this.#rest.patch(Routes.guildRole(this.guildId, roleId), {
1643
- ...payload,
1644
- permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
1645
- });
1646
- const role = new Role(data);
1647
- this.set(role.id, role);
1648
- return role;
1649
- }
1650
- async deleteRole(roleId) {
1651
- await this.#rest.delete(Routes.guildRole(this.guildId, roleId));
1652
- this.delete(roleId);
1653
- }
1654
- }
1655
- // packages/managers/src/member.ts
1656
- class GuildMemberManager extends ResourceManager {
1657
- #rest;
1658
- guildId;
1659
- constructor(guildId, rest) {
1660
- super((id) => rest.get(Routes.guildMember(guildId, id)).then((data) => new GuildMember({ ...data, guild_id: guildId })), (member) => member.user.id);
1661
- this.guildId = guildId;
1662
- this.#rest = rest;
1663
- }
1664
- async kick(userId) {
1665
- await this.#rest.delete(Routes.guildMember(this.guildId, userId));
1666
- this.delete(userId);
1667
- }
1668
- async ban(userId, options = {}) {
1669
- await this.#rest.put(Routes.guildBan(this.guildId, userId), {
1670
- delete_message_seconds: options.deleteMessageSeconds
1671
- });
1672
- this.delete(userId);
1673
- }
1674
- async unban(userId) {
1675
- await this.#rest.delete(Routes.guildBan(this.guildId, userId));
1676
- }
1677
- async edit(userId, options) {
1678
- const data = await this.#rest.patch(Routes.guildMember(this.guildId, userId), options);
1679
- const member = new GuildMember({ ...data, guild_id: this.guildId });
1680
- this.set(member.user.id, member);
1681
- return member;
1682
- }
1683
- async addRole(userId, roleId) {
1684
- await this.#rest.put(Routes.guildMemberRole(this.guildId, userId, roleId));
1685
- }
1686
- async removeRole(userId, roleId) {
1687
- await this.#rest.delete(Routes.guildMemberRole(this.guildId, userId, roleId));
1688
- }
1689
- async timeout(userId, milliseconds) {
1690
- const timeoutDate = milliseconds === null ? null : new Date(Date.now() + milliseconds).toISOString();
1691
- return this.edit(userId, { communication_disabled_until: timeoutDate });
1692
- }
1693
- }
1694
2695
  // packages/managers/src/application.ts
1695
2696
  class ApplicationCommandManager {
1696
2697
  #rest;
@@ -1730,53 +2731,22 @@ class ApplicationCommandManager {
1730
2731
  await this.#rest.delete(Routes.guildApplicationCommand(this.#applicationId, guildId, commandId));
1731
2732
  }
1732
2733
  }
1733
- // packages/managers/src/emoji.ts
1734
- class EmojiManager extends Manager {
1735
- #rest;
1736
- #guildId;
1737
- constructor(rest, guildId) {
1738
- super();
1739
- this.#rest = rest;
1740
- this.#guildId = guildId;
1741
- }
1742
- async fetch(emojiId) {
1743
- return this.upsert(await this.#rest.get(Routes.guildEmoji(this.#guildId, emojiId)));
1744
- }
1745
- async fetchAll() {
1746
- const data = await this.#rest.get(Routes.guildEmoji(this.#guildId));
1747
- return data.map((item) => this.upsert(item));
1748
- }
1749
- async create(options) {
1750
- return this.upsert(await this.#rest.post(Routes.guildEmoji(this.#guildId), options));
1751
- }
1752
- async edit(emojiId, options) {
1753
- return this.upsert(await this.#rest.patch(Routes.guildEmoji(this.#guildId, emojiId), options));
1754
- }
1755
- async deleteEmoji(emojiId) {
1756
- await this.#rest.delete(Routes.guildEmoji(this.#guildId, emojiId));
1757
- this.delete(emojiId);
1758
- }
1759
- upsert(data) {
1760
- const key = data.id != null ? data.id : `unicode:${data.name ?? ""}`;
1761
- const existing = this.get(key);
1762
- const emoji = new Emoji(data);
1763
- if (existing) {
1764
- Object.assign(existing, emoji);
1765
- return existing;
1766
- }
1767
- this.set(key, emoji);
1768
- return emoji;
1769
- }
1770
- }
1771
2734
 
1772
2735
  // packages/managers/src/index.ts
2736
+ var BULK_DELETE_MAX_AGE_MS = 14 * 24 * 60 * 60000;
2737
+ function snowflakeTime(id) {
2738
+ return Number((BigInt(id) >> 22n) + 1420070400000n);
2739
+ }
2740
+
1773
2741
  class ChannelManager extends Manager {
1774
2742
  #rest;
1775
2743
  #context;
1776
2744
  #messageManagers = new Map;
1777
- constructor(rest) {
2745
+ #messageCache;
2746
+ constructor(rest, options = {}) {
1778
2747
  super();
1779
2748
  this.#rest = rest;
2749
+ this.#messageCache = options.messageCache;
1780
2750
  this.#context = {
1781
2751
  sendMessage: (channelId, options) => this.send(channelId, options),
1782
2752
  editMessage: (channelId, messageId, options) => this.editMessage(channelId, messageId, options),
@@ -1795,24 +2765,29 @@ class ChannelManager extends Manager {
1795
2765
  messages(channelId) {
1796
2766
  let manager = this.#messageManagers.get(channelId);
1797
2767
  if (!manager) {
1798
- manager = new MessageManager(this.#rest, this.#context, channelId);
2768
+ manager = new MessageManager(this.#rest, this.#context, channelId, this.#messageCache);
1799
2769
  this.#messageManagers.set(channelId, manager);
1800
2770
  }
1801
2771
  return manager;
1802
2772
  }
2773
+ permissionOverwrites(channelId) {
2774
+ return new PermissionOverwriteManager(this.#rest, channelId);
2775
+ }
1803
2776
  threads(channelId) {
1804
2777
  return new ThreadManager(this.#rest, this.#context, channelId);
1805
2778
  }
1806
- async fetch(channelId) {
1807
- return this.upsert(await this.#rest.get(Routes.channel(channelId)));
2779
+ fetch(channelId) {
2780
+ return this.fetchOnce(channelId, async () => createChannel2(await this.#rest.get(Routes.channel(channelId)), this.#context), (channel) => this.#merge(channel));
1808
2781
  }
1809
2782
  async resolve(channelId) {
1810
2783
  return this.get(channelId) ?? this.fetch(channelId);
1811
2784
  }
1812
2785
  upsert(data) {
1813
- const existing = this.get(data.id);
1814
- const channel = new Channel(data, this.#context);
1815
- if (existing) {
2786
+ return this.#merge(createChannel2(data, this.#context));
2787
+ }
2788
+ #merge(channel) {
2789
+ const existing = this.get(channel.id);
2790
+ if (existing && existing.type === channel.type) {
1816
2791
  Object.assign(existing, channel);
1817
2792
  return existing;
1818
2793
  }
@@ -1822,6 +2797,37 @@ class ChannelManager extends Manager {
1822
2797
  update(channel) {
1823
2798
  return this.set(channel.id, channel);
1824
2799
  }
2800
+ deleteGuildChannels(guildId) {
2801
+ let removed = 0;
2802
+ for (const channel of this.values())
2803
+ if (channel.guildId === guildId && this.delete(channel.id))
2804
+ removed++;
2805
+ return removed;
2806
+ }
2807
+ async endPoll(channelId, messageId) {
2808
+ return this.messages(channelId).upsert(await this.#rest.post(Routes.pollExpire(channelId, messageId)));
2809
+ }
2810
+ async fetchPollVoters(channelId, messageId, answerId, options = {}) {
2811
+ if (options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100))
2812
+ throw new RangeError("Poll voter limit must be 1-100.");
2813
+ const params = new URLSearchParams;
2814
+ if (options.after)
2815
+ params.set("after", options.after);
2816
+ if (options.limit !== undefined)
2817
+ params.set("limit", String(options.limit));
2818
+ const suffix = params.toString();
2819
+ const { users } = await this.#rest.get(`${Routes.pollAnswerVoters(channelId, messageId, answerId)}${suffix ? `?${suffix}` : ""}`);
2820
+ return users.map((user) => new User(user));
2821
+ }
2822
+ async sendSoundboardSound(channelId, options) {
2823
+ await this.#rest.post(Routes.sendSoundboardSound(channelId), {
2824
+ sound_id: options.soundId,
2825
+ source_guild_id: options.sourceGuildId
2826
+ });
2827
+ }
2828
+ cachedMessages(channelId) {
2829
+ return this.#messageManagers.get(channelId);
2830
+ }
1825
2831
  async create(guildId, options) {
1826
2832
  return this.upsert(await this.#rest.post(Routes.guildChannels(guildId), options));
1827
2833
  }
@@ -1878,15 +2884,37 @@ class ChannelManager extends Manager {
1878
2884
  return this.messages(channelId).upsert(await this.#rest.post(Routes.crosspostMessage(channelId, messageId)));
1879
2885
  }
1880
2886
  async bulkDeleteMessages(channelId, messageIds) {
1881
- const ids = [...messageIds];
1882
- if (ids.length < 2 || ids.length > 100)
1883
- throw new RangeError("bulkDelete requires between 2 and 100 message IDs.");
2887
+ const ids = [...new Set(messageIds)];
2888
+ if (ids.length < 1 || ids.length > 100)
2889
+ throw new RangeError("bulkDelete requires between 1 and 100 message IDs.");
2890
+ if (ids.length === 1)
2891
+ return this.deleteMessage(channelId, ids[0]);
2892
+ const cutoff = Date.now() - BULK_DELETE_MAX_AGE_MS;
2893
+ const tooOld = ids.filter((id) => snowflakeTime(id) < cutoff);
2894
+ if (tooOld.length)
2895
+ throw new RangeError(`bulkDelete cannot delete messages older than 14 days: ${tooOld.join(", ")}`);
1884
2896
  await this.#rest.post(Routes.channelBulkDelete(channelId), {
1885
2897
  messages: ids
1886
2898
  });
1887
2899
  for (const id of ids)
1888
2900
  this.messages(channelId).delete(id);
1889
2901
  }
2902
+ async* iterateMessages(channelId, options = {}) {
2903
+ let before = options.before;
2904
+ let remaining = options.limit ?? Infinity;
2905
+ while (remaining > 0) {
2906
+ const page = await this.fetchMessages(channelId, {
2907
+ before,
2908
+ limit: Math.min(100, remaining)
2909
+ });
2910
+ for (const message of page)
2911
+ yield message;
2912
+ remaining -= page.length;
2913
+ if (page.length < 100)
2914
+ return;
2915
+ before = page.at(-1).id;
2916
+ }
2917
+ }
1890
2918
  async addReaction(channelId, messageId, emoji) {
1891
2919
  await this.#rest.put(`${Routes.messageReactions(channelId, messageId, emoji)}/@me`);
1892
2920
  }
@@ -1949,16 +2977,24 @@ function isMessageQuery(value) {
1949
2977
  export {
1950
2978
  ApplicationCommandManager,
1951
2979
  AuditLogEvent,
2980
+ ResourceManager as CachedManager,
1952
2981
  ChannelManager,
1953
2982
  EmojiManager,
2983
+ GuildBanManager,
1954
2984
  GuildManager,
1955
2985
  GuildMemberManager,
2986
+ GuildScheduledEventManager,
2987
+ GuildSoundboardManager,
2988
+ GuildStickerManager,
1956
2989
  Manager,
1957
2990
  MessageManager,
2991
+ MonetizationManager,
2992
+ PermissionOverwriteManager,
1958
2993
  ResourceManager,
1959
2994
  RoleManager,
2995
+ StageInstanceManager,
1960
2996
  ThreadManager,
1961
2997
  UserManager
1962
2998
  };
1963
2999
 
1964
- //# debugId=EA438691ADA8387364756E2164756E21
3000
+ //# debugId=DAACDF8C2AA7984564756E2164756E21