lunibee 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +225 -225
- package/dist/builders/attachment.d.ts +8 -0
- package/dist/builders/commands.d.ts +122 -65
- package/dist/builders/components.d.ts +10 -31
- package/dist/builders/embed.d.ts +66 -33
- package/dist/builders/index.js +97 -131
- package/dist/builders/index.js.map +8 -8
- package/dist/collection/cache.d.ts +13 -6
- package/dist/collection/index.d.ts +90 -17
- package/dist/collection/index.js +442 -266
- package/dist/collection/index.js.map +4 -4
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +607 -352
- package/dist/core/index.js.map +47 -47
- package/dist/core/permissions.d.ts +7 -3
- package/dist/formatters/index.js +9 -5
- package/dist/formatters/index.js.map +3 -3
- package/dist/handlers/index.js +5 -10
- package/dist/handlers/index.js.map +3 -3
- package/dist/index.js +769 -587
- package/dist/index.js.map +65 -65
- package/dist/managers/base.d.ts +22 -14
- package/dist/managers/index.d.ts +2 -1
- package/dist/managers/index.js +445 -276
- package/dist/managers/index.js.map +26 -26
- package/dist/managers/message.d.ts +7 -3
- package/dist/rest/errors.d.ts +14 -7
- package/dist/rest/index.d.ts +24 -12
- package/dist/rest/index.js +54 -17
- package/dist/rest/index.js.map +14 -14
- package/dist/rest/redis.d.ts +1 -1
- package/dist/rest/route.d.ts +8 -4
- package/dist/rest/routes.d.ts +102 -48
- package/dist/rest/transport.d.ts +10 -5
- package/dist/rest/webhook.d.ts +9 -5
- package/dist/sharding/bus.d.ts +34 -17
- package/dist/sharding/index.d.ts +34 -17
- package/dist/sharding/index.js +64 -32
- package/dist/sharding/index.js.map +17 -17
- package/dist/structures/base.d.ts +19 -10
- package/dist/structures/channels.d.ts +28 -14
- package/dist/structures/index.js +9 -59
- package/dist/structures/index.js.map +19 -18
- package/dist/structures/interactions.d.ts +96 -48
- package/dist/structures/resources.d.ts +88 -44
- package/dist/types/gateway.d.ts +1 -1
- package/dist/types/index.js +20 -22
- package/dist/types/index.js.map +4 -4
- package/dist/utils/index.js.map +2 -2
- package/dist/voice/index.d.ts +12 -4
- package/dist/voice/index.js +14 -18
- package/dist/voice/index.js.map +3 -3
- package/dist/ws/decoder.d.ts +6 -2
- package/dist/ws/index.d.ts +25 -13
- package/dist/ws/index.js +63 -31
- package/dist/ws/index.js.map +14 -14
- package/dist/ws/protocol.d.ts +10 -2
- package/dist/ws/session.d.ts +14 -4
- package/dist/ws/state.d.ts +22 -11
- package/package.json +15 -14
package/dist/index.js
CHANGED
|
@@ -114,60 +114,7 @@ var Permissions = {
|
|
|
114
114
|
PinMessages: 1n << 51n,
|
|
115
115
|
BypassSlowmode: 1n << 52n
|
|
116
116
|
};
|
|
117
|
-
var PermissionFlagsBits =
|
|
118
|
-
CreateInstantInvite: 1n << 0n,
|
|
119
|
-
KickMembers: 1n << 1n,
|
|
120
|
-
BanMembers: 1n << 2n,
|
|
121
|
-
Administrator: 1n << 3n,
|
|
122
|
-
ManageChannels: 1n << 4n,
|
|
123
|
-
ManageGuild: 1n << 5n,
|
|
124
|
-
AddReactions: 1n << 6n,
|
|
125
|
-
ViewAuditLog: 1n << 7n,
|
|
126
|
-
PrioritySpeaker: 1n << 8n,
|
|
127
|
-
Stream: 1n << 9n,
|
|
128
|
-
ViewChannel: 1n << 10n,
|
|
129
|
-
SendMessages: 1n << 11n,
|
|
130
|
-
SendTTSMessages: 1n << 12n,
|
|
131
|
-
ManageMessages: 1n << 13n,
|
|
132
|
-
EmbedLinks: 1n << 14n,
|
|
133
|
-
AttachFiles: 1n << 15n,
|
|
134
|
-
ReadMessageHistory: 1n << 16n,
|
|
135
|
-
MentionEveryone: 1n << 17n,
|
|
136
|
-
UseExternalEmojis: 1n << 18n,
|
|
137
|
-
ViewGuildInsights: 1n << 19n,
|
|
138
|
-
Connect: 1n << 20n,
|
|
139
|
-
Speak: 1n << 21n,
|
|
140
|
-
MuteMembers: 1n << 22n,
|
|
141
|
-
DeafenMembers: 1n << 23n,
|
|
142
|
-
MoveMembers: 1n << 24n,
|
|
143
|
-
UseVAD: 1n << 25n,
|
|
144
|
-
ChangeNickname: 1n << 26n,
|
|
145
|
-
ManageNicknames: 1n << 27n,
|
|
146
|
-
ManageRoles: 1n << 28n,
|
|
147
|
-
ManageWebhooks: 1n << 29n,
|
|
148
|
-
ManageGuildExpressions: 1n << 30n,
|
|
149
|
-
UseApplicationCommands: 1n << 31n,
|
|
150
|
-
RequestToSpeak: 1n << 32n,
|
|
151
|
-
ManageEvents: 1n << 33n,
|
|
152
|
-
ManageThreads: 1n << 34n,
|
|
153
|
-
CreatePublicThreads: 1n << 35n,
|
|
154
|
-
CreatePrivateThreads: 1n << 36n,
|
|
155
|
-
UseExternalStickers: 1n << 37n,
|
|
156
|
-
SendMessagesInThreads: 1n << 38n,
|
|
157
|
-
UseEmbeddedActivities: 1n << 39n,
|
|
158
|
-
ModerateMembers: 1n << 40n,
|
|
159
|
-
ViewCreatorMonetizationAnalytics: 1n << 41n,
|
|
160
|
-
UseSoundboard: 1n << 42n,
|
|
161
|
-
CreateGuildExpressions: 1n << 43n,
|
|
162
|
-
CreateEvents: 1n << 44n,
|
|
163
|
-
UseExternalSounds: 1n << 45n,
|
|
164
|
-
SendVoiceMessages: 1n << 46n,
|
|
165
|
-
SetVoiceChannelStatus: 1n << 48n,
|
|
166
|
-
SendPolls: 1n << 49n,
|
|
167
|
-
UseExternalApps: 1n << 50n,
|
|
168
|
-
PinMessages: 1n << 51n,
|
|
169
|
-
BypassSlowmode: 1n << 52n
|
|
170
|
-
};
|
|
117
|
+
var PermissionFlagsBits = Permissions;
|
|
171
118
|
|
|
172
119
|
class PermissionSet {
|
|
173
120
|
bitfield;
|
|
@@ -468,6 +415,9 @@ function computePermissions(context) {
|
|
|
468
415
|
const member = overwrites.find((o) => o.type === 1 /* Member */ && o.id === context.memberId);
|
|
469
416
|
if (member)
|
|
470
417
|
base = base & ~bits(member.deny) | bits(member.allow);
|
|
418
|
+
const until = context.timedOutUntil instanceof Date ? context.timedOutUntil.getTime() : context.timedOutUntil ?? 0;
|
|
419
|
+
if (until > Date.now())
|
|
420
|
+
base &= Permission.viewChannel | Permission.readMessageHistory;
|
|
471
421
|
return new PermissionSet(base);
|
|
472
422
|
}
|
|
473
423
|
// packages/core/src/events.ts
|
|
@@ -742,28 +692,26 @@ var IntentBits = {
|
|
|
742
692
|
};
|
|
743
693
|
var Intents = IntentBits;
|
|
744
694
|
function resolveGatewayIntents(intents) {
|
|
745
|
-
if (
|
|
746
|
-
return intents;
|
|
747
|
-
if (
|
|
695
|
+
if (Array.isArray(intents))
|
|
696
|
+
return intents.reduce((acc, intent) => acc | resolveIntent(intent), 0);
|
|
697
|
+
if (typeof intents === "object")
|
|
748
698
|
return intents.bitfield;
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
}
|
|
766
|
-
return 0;
|
|
699
|
+
return resolveIntent(intents);
|
|
700
|
+
}
|
|
701
|
+
function resolveIntent(intent) {
|
|
702
|
+
if (typeof intent === "number")
|
|
703
|
+
return intent;
|
|
704
|
+
const bits = {
|
|
705
|
+
...IntentBits,
|
|
706
|
+
...GatewayIntentBits
|
|
707
|
+
};
|
|
708
|
+
const lower = intent.charAt(0).toLowerCase() + intent.slice(1);
|
|
709
|
+
if (Object.hasOwn(bits, intent))
|
|
710
|
+
return bits[intent];
|
|
711
|
+
if (Object.hasOwn(bits, lower))
|
|
712
|
+
return bits[lower];
|
|
713
|
+
const num = Number(intent);
|
|
714
|
+
return Number.isNaN(num) ? 0 : num;
|
|
767
715
|
}
|
|
768
716
|
|
|
769
717
|
class IntentsBitField {
|
|
@@ -830,6 +778,24 @@ var ChannelEnum = {
|
|
|
830
778
|
GuildForum: 15,
|
|
831
779
|
GuildMedia: 16
|
|
832
780
|
};
|
|
781
|
+
var ComponentEnum = {
|
|
782
|
+
ActionRow: 1,
|
|
783
|
+
Button: 2,
|
|
784
|
+
StringSelect: 3,
|
|
785
|
+
TextInput: 4,
|
|
786
|
+
UserSelect: 5,
|
|
787
|
+
RoleSelect: 6,
|
|
788
|
+
MentionableSelect: 7,
|
|
789
|
+
ChannelSelect: 8,
|
|
790
|
+
Section: 9,
|
|
791
|
+
TextDisplay: 10,
|
|
792
|
+
Thumbnail: 11,
|
|
793
|
+
MediaGallery: 12,
|
|
794
|
+
File: 13,
|
|
795
|
+
Separator: 14,
|
|
796
|
+
ContentInventoryEntry: 16,
|
|
797
|
+
Container: 17
|
|
798
|
+
};
|
|
833
799
|
var ButtonType = {
|
|
834
800
|
Primary: 1,
|
|
835
801
|
Secondary: 2,
|
|
@@ -904,64 +870,36 @@ var StickerType = StickerEnum;
|
|
|
904
870
|
var StickerFormatType = StickerFormatEnum;
|
|
905
871
|
// packages/collection/src/cache.ts
|
|
906
872
|
class Cache {
|
|
907
|
-
#entries
|
|
908
|
-
#maxSize;
|
|
909
|
-
#ttl;
|
|
910
|
-
#timer;
|
|
873
|
+
#entries;
|
|
911
874
|
constructor(options = {}) {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
if (!Number.isInteger(
|
|
875
|
+
const maxSize = options.maxSize ?? Infinity;
|
|
876
|
+
const ttl = options.ttl ?? 0;
|
|
877
|
+
if (!Number.isInteger(maxSize) && maxSize !== Infinity || maxSize < 1)
|
|
915
878
|
throw new RangeError("Cache maxSize must be a positive integer.");
|
|
916
|
-
if (!Number.isFinite(
|
|
879
|
+
if (!Number.isFinite(ttl) || ttl < 0)
|
|
917
880
|
throw new RangeError("Cache ttl must be a non-negative finite number.");
|
|
918
|
-
if (
|
|
919
|
-
const interval = options.sweepInterval ?? Math.min(
|
|
881
|
+
if (ttl > 0) {
|
|
882
|
+
const interval = options.sweepInterval ?? Math.min(ttl, 60000);
|
|
920
883
|
if (!Number.isFinite(interval) || interval < 1)
|
|
921
884
|
throw new RangeError("Cache sweepInterval must be positive.");
|
|
922
|
-
this.#timer = setInterval(() => this.sweep(), interval);
|
|
923
|
-
this.#timer.unref?.();
|
|
924
885
|
}
|
|
886
|
+
this.#entries = new Collection(null, {
|
|
887
|
+
ttl: ttl > 0 ? ttl : undefined,
|
|
888
|
+
maxSize: maxSize === Infinity ? undefined : maxSize,
|
|
889
|
+
slide: false
|
|
890
|
+
});
|
|
925
891
|
}
|
|
926
892
|
get size() {
|
|
927
|
-
this.#sweepExpired();
|
|
928
893
|
return this.#entries.size;
|
|
929
894
|
}
|
|
930
895
|
get(key) {
|
|
931
|
-
|
|
932
|
-
if (!entry)
|
|
933
|
-
return;
|
|
934
|
-
if (entry.expiresAt > 0 && entry.expiresAt <= Date.now()) {
|
|
935
|
-
this.#entries.delete(key);
|
|
936
|
-
return;
|
|
937
|
-
}
|
|
938
|
-
this.#entries.delete(key);
|
|
939
|
-
this.#entries.set(key, entry);
|
|
940
|
-
return entry.value;
|
|
896
|
+
return this.#entries.get(key);
|
|
941
897
|
}
|
|
942
898
|
has(key) {
|
|
943
|
-
|
|
944
|
-
if (!entry)
|
|
945
|
-
return false;
|
|
946
|
-
if (entry.expiresAt > 0 && entry.expiresAt <= Date.now()) {
|
|
947
|
-
this.#entries.delete(key);
|
|
948
|
-
return false;
|
|
949
|
-
}
|
|
950
|
-
return true;
|
|
899
|
+
return this.#entries.has(key);
|
|
951
900
|
}
|
|
952
901
|
set(key, value) {
|
|
953
|
-
|
|
954
|
-
this.#entries.delete(key);
|
|
955
|
-
this.#entries.set(key, { value, expiresAt });
|
|
956
|
-
if (this.#maxSize !== Infinity) {
|
|
957
|
-
while (this.#entries.size > this.#maxSize) {
|
|
958
|
-
const oldest = this.#entries.firstKey();
|
|
959
|
-
if (oldest !== undefined)
|
|
960
|
-
this.#entries.delete(oldest);
|
|
961
|
-
else
|
|
962
|
-
break;
|
|
963
|
-
}
|
|
964
|
-
}
|
|
902
|
+
this.#entries.set(key, value);
|
|
965
903
|
return this;
|
|
966
904
|
}
|
|
967
905
|
delete(key) {
|
|
@@ -971,95 +909,52 @@ class Cache {
|
|
|
971
909
|
this.#entries.clear();
|
|
972
910
|
}
|
|
973
911
|
invalidate(predicate) {
|
|
974
|
-
return this.#entries.sweep(
|
|
912
|
+
return this.#entries.sweep(predicate);
|
|
975
913
|
}
|
|
976
914
|
sweep() {
|
|
977
|
-
return this.#entries.
|
|
978
|
-
}
|
|
979
|
-
dispose() {
|
|
980
|
-
if (this.#timer)
|
|
981
|
-
clearInterval(this.#timer);
|
|
982
|
-
this.#timer = undefined;
|
|
915
|
+
return this.#entries.purge();
|
|
983
916
|
}
|
|
917
|
+
dispose() {}
|
|
984
918
|
values() {
|
|
985
|
-
this.#
|
|
986
|
-
return this.#entries.map((entry) => entry.value);
|
|
919
|
+
return [...this.#entries.values()];
|
|
987
920
|
}
|
|
988
921
|
entries() {
|
|
989
|
-
this.#
|
|
990
|
-
return this.#entries.map((entry, key) => [key, entry.value]);
|
|
991
|
-
}
|
|
992
|
-
#expired(entry) {
|
|
993
|
-
return entry.expiresAt > 0 && entry.expiresAt <= Date.now();
|
|
994
|
-
}
|
|
995
|
-
#sweepExpired() {
|
|
996
|
-
if (this.#ttl > 0)
|
|
997
|
-
this.sweep();
|
|
922
|
+
return [...this.#entries.entries()];
|
|
998
923
|
}
|
|
999
924
|
}
|
|
1000
925
|
|
|
1001
926
|
// packages/collection/src/index.ts
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
const node = this.#nodes.get(key);
|
|
1031
|
-
if (!node)
|
|
1032
|
-
return false;
|
|
1033
|
-
this.#unlink(node);
|
|
1034
|
-
this.#nodes.delete(key);
|
|
1035
|
-
return true;
|
|
1036
|
-
}
|
|
1037
|
-
clear() {
|
|
1038
|
-
this.#nodes.clear();
|
|
1039
|
-
this.#oldest = this.#newest = undefined;
|
|
1040
|
-
}
|
|
1041
|
-
#unlink(node) {
|
|
1042
|
-
if (node.older)
|
|
1043
|
-
node.older.newer = node.newer;
|
|
1044
|
-
else
|
|
1045
|
-
this.#oldest = node.newer;
|
|
1046
|
-
if (node.newer)
|
|
1047
|
-
node.newer.older = node.older;
|
|
1048
|
-
else
|
|
1049
|
-
this.#newest = node.older;
|
|
1050
|
-
node.older = node.newer = undefined;
|
|
1051
|
-
}
|
|
1052
|
-
#moveNewest(node) {
|
|
1053
|
-
if (node === this.#newest)
|
|
1054
|
-
return;
|
|
1055
|
-
this.#unlink(node);
|
|
1056
|
-
node.older = this.#newest;
|
|
1057
|
-
if (this.#newest)
|
|
1058
|
-
this.#newest.newer = node;
|
|
1059
|
-
else
|
|
1060
|
-
this.#oldest = node;
|
|
1061
|
-
this.#newest = node;
|
|
927
|
+
function newPolicy(options = {}) {
|
|
928
|
+
return {
|
|
929
|
+
ttl: options.ttl,
|
|
930
|
+
maxSize: options.maxSize,
|
|
931
|
+
slide: options.slide ?? true,
|
|
932
|
+
onEvict: options.onEvict,
|
|
933
|
+
expired: 0,
|
|
934
|
+
evicted: 0,
|
|
935
|
+
entries: new Map,
|
|
936
|
+
oldest: undefined,
|
|
937
|
+
newest: undefined,
|
|
938
|
+
lruSize: 0,
|
|
939
|
+
heap: [],
|
|
940
|
+
armedFor: Infinity
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
function peekOf(collection, key) {
|
|
944
|
+
return collection instanceof Map ? Map.prototype.get.call(collection, key) : collection.get(key);
|
|
945
|
+
}
|
|
946
|
+
var mapGet = Map.prototype.get;
|
|
947
|
+
var mapHas = Map.prototype.has;
|
|
948
|
+
function sample(items, amount) {
|
|
949
|
+
if (!Number.isInteger(amount) || amount < 0)
|
|
950
|
+
throw new RangeError("amount must be a non-negative integer.");
|
|
951
|
+
const count = Math.min(amount, items.length);
|
|
952
|
+
for (let i = 0;i < count; i++) {
|
|
953
|
+
const j = i + Math.floor(Math.random() * (items.length - i));
|
|
954
|
+
[items[i], items[j]] = [items[j], items[i]];
|
|
1062
955
|
}
|
|
956
|
+
items.length = count;
|
|
957
|
+
return items;
|
|
1063
958
|
}
|
|
1064
959
|
function assertTTL(ttl) {
|
|
1065
960
|
if (ttl !== undefined && (!Number.isFinite(ttl) || ttl <= 0))
|
|
@@ -1067,81 +962,90 @@ function assertTTL(ttl) {
|
|
|
1067
962
|
}
|
|
1068
963
|
|
|
1069
964
|
class Collection extends Map {
|
|
1070
|
-
#
|
|
1071
|
-
#
|
|
1072
|
-
#
|
|
1073
|
-
#expiry = new Map;
|
|
1074
|
-
#lru = new RecencyList;
|
|
1075
|
-
#stats = {
|
|
1076
|
-
hits: 0,
|
|
1077
|
-
misses: 0,
|
|
1078
|
-
expired: 0,
|
|
1079
|
-
evicted: 0
|
|
1080
|
-
};
|
|
1081
|
-
#heap = [];
|
|
1082
|
-
#timer;
|
|
1083
|
-
#armedFor = Infinity;
|
|
965
|
+
#policy;
|
|
966
|
+
#hits = 0;
|
|
967
|
+
#misses = 0;
|
|
1084
968
|
constructor(entries, options = {}) {
|
|
1085
969
|
super();
|
|
1086
970
|
assertTTL(options.ttl);
|
|
1087
971
|
if (options.maxSize !== undefined && (!Number.isInteger(options.maxSize) || options.maxSize <= 0))
|
|
1088
972
|
throw new RangeError("maxSize must be a positive integer.");
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
this.#onEvict = options.onEvict;
|
|
973
|
+
if (options.ttl !== undefined || options.maxSize !== undefined || options.slide !== undefined || options.onEvict !== undefined)
|
|
974
|
+
this.#policy = newPolicy(options);
|
|
1092
975
|
if (entries)
|
|
1093
976
|
for (const [key, value] of entries)
|
|
1094
977
|
this.set(key, value);
|
|
1095
978
|
}
|
|
1096
979
|
set(key, value, ttl) {
|
|
980
|
+
if (ttl === undefined && this.#policy === undefined)
|
|
981
|
+
return super.set(key, value);
|
|
1097
982
|
assertTTL(ttl);
|
|
1098
|
-
const window = ttl ?? this.#ttl;
|
|
1099
|
-
if (this.#maxSize !== undefined) {
|
|
1100
|
-
this.#lru.touch(key);
|
|
1101
|
-
}
|
|
1102
|
-
super.set(key, value);
|
|
983
|
+
const window = ttl ?? this.#policy?.ttl;
|
|
1103
984
|
if (window !== undefined)
|
|
1104
|
-
this.#
|
|
1105
|
-
|
|
1106
|
-
|
|
985
|
+
this.#policy ??= newPolicy();
|
|
986
|
+
if (!this.#policy)
|
|
987
|
+
return super.set(key, value);
|
|
988
|
+
const before = super.size;
|
|
989
|
+
super.set(key, value);
|
|
990
|
+
this.#track(key, value, window, super.size !== before);
|
|
1107
991
|
this.#enforceCap();
|
|
1108
992
|
return this;
|
|
1109
993
|
}
|
|
1110
994
|
setWithoutTTL(key, value) {
|
|
1111
|
-
if (this.#
|
|
1112
|
-
this.#
|
|
1113
|
-
if (this.#lru.size > 0)
|
|
1114
|
-
this.#lru.delete(key);
|
|
995
|
+
if (this.#policy)
|
|
996
|
+
this.#forget(key);
|
|
1115
997
|
super.set(key, value);
|
|
1116
998
|
return this;
|
|
1117
999
|
}
|
|
1118
1000
|
get(key) {
|
|
1119
|
-
|
|
1120
|
-
|
|
1001
|
+
const policy = this.#policy;
|
|
1002
|
+
const entry = policy?.entries.get(key);
|
|
1003
|
+
if (entry === undefined) {
|
|
1004
|
+
const value = mapGet.call(this, key);
|
|
1005
|
+
if (value !== undefined || mapHas.call(this, key)) {
|
|
1006
|
+
this.#hits++;
|
|
1007
|
+
return value;
|
|
1008
|
+
}
|
|
1009
|
+
this.#misses++;
|
|
1121
1010
|
return;
|
|
1122
1011
|
}
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1125
|
-
|
|
1012
|
+
const timed = entry.window !== 0;
|
|
1013
|
+
const now = timed ? Date.now() : 0;
|
|
1014
|
+
if (timed && entry.deadline <= now) {
|
|
1015
|
+
this.#expire(entry);
|
|
1016
|
+
this.#misses++;
|
|
1126
1017
|
return;
|
|
1127
1018
|
}
|
|
1128
|
-
this.#
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
return value;
|
|
1019
|
+
this.#hits++;
|
|
1020
|
+
if (timed && policy.slide)
|
|
1021
|
+
entry.deadline = now + entry.window;
|
|
1022
|
+
if (entry.inLru)
|
|
1023
|
+
this.#promote(policy, entry);
|
|
1024
|
+
return entry.value;
|
|
1025
|
+
}
|
|
1026
|
+
ensure(key, factory, ttl) {
|
|
1027
|
+
const existing = this.get(key);
|
|
1028
|
+
if (existing !== undefined || super.has(key))
|
|
1029
|
+
return existing;
|
|
1030
|
+
const created = factory(key, this);
|
|
1031
|
+
this.set(key, created, ttl);
|
|
1032
|
+
return created;
|
|
1134
1033
|
}
|
|
1135
1034
|
peek(key) {
|
|
1136
1035
|
if (!this.#expireIfDue(key) && super.has(key)) {
|
|
1137
|
-
this.#
|
|
1036
|
+
this.#hits++;
|
|
1138
1037
|
return super.get(key);
|
|
1139
1038
|
}
|
|
1140
|
-
this.#
|
|
1039
|
+
this.#misses++;
|
|
1141
1040
|
return;
|
|
1142
1041
|
}
|
|
1143
1042
|
get stats() {
|
|
1144
|
-
return {
|
|
1043
|
+
return {
|
|
1044
|
+
hits: this.#hits,
|
|
1045
|
+
misses: this.#misses,
|
|
1046
|
+
expired: this.#policy?.expired ?? 0,
|
|
1047
|
+
evicted: this.#policy?.evicted ?? 0
|
|
1048
|
+
};
|
|
1145
1049
|
}
|
|
1146
1050
|
has(key) {
|
|
1147
1051
|
return !this.#expireIfDue(key) && super.has(key);
|
|
@@ -1149,19 +1053,23 @@ class Collection extends Map {
|
|
|
1149
1053
|
delete(key) {
|
|
1150
1054
|
if (this.#expireIfDue(key))
|
|
1151
1055
|
return false;
|
|
1152
|
-
this.#
|
|
1153
|
-
|
|
1056
|
+
if (this.#policy)
|
|
1057
|
+
this.#forget(key);
|
|
1154
1058
|
return super.delete(key);
|
|
1155
1059
|
}
|
|
1156
1060
|
clear() {
|
|
1157
1061
|
super.clear();
|
|
1158
|
-
this.#
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1062
|
+
const policy = this.#policy;
|
|
1063
|
+
if (!policy)
|
|
1064
|
+
return;
|
|
1065
|
+
policy.entries.clear();
|
|
1066
|
+
policy.oldest = policy.newest = undefined;
|
|
1067
|
+
policy.lruSize = 0;
|
|
1068
|
+
policy.heap.length = 0;
|
|
1069
|
+
if (policy.timer)
|
|
1070
|
+
clearTimeout(policy.timer);
|
|
1071
|
+
policy.timer = undefined;
|
|
1072
|
+
policy.armedFor = Infinity;
|
|
1165
1073
|
}
|
|
1166
1074
|
get size() {
|
|
1167
1075
|
this.purge();
|
|
@@ -1189,11 +1097,11 @@ class Collection extends Map {
|
|
|
1189
1097
|
ttlRemaining(key) {
|
|
1190
1098
|
if (this.#expireIfDue(key))
|
|
1191
1099
|
return;
|
|
1192
|
-
const
|
|
1193
|
-
return
|
|
1100
|
+
const entry = this.#policy?.entries.get(key);
|
|
1101
|
+
return entry && entry.window !== 0 ? Math.max(0, entry.deadline - Date.now()) : undefined;
|
|
1194
1102
|
}
|
|
1195
1103
|
purge() {
|
|
1196
|
-
if (this.#
|
|
1104
|
+
if (!this.#policy || this.#policy.heap.length === 0)
|
|
1197
1105
|
return 0;
|
|
1198
1106
|
const now = Date.now();
|
|
1199
1107
|
let removed = 0;
|
|
@@ -1204,133 +1112,255 @@ class Collection extends Map {
|
|
|
1204
1112
|
this.#remove(due.key);
|
|
1205
1113
|
removed++;
|
|
1206
1114
|
}
|
|
1207
|
-
this.#
|
|
1115
|
+
this.#policy.expired += removed;
|
|
1208
1116
|
this.#rearm();
|
|
1209
1117
|
for (const [key, value] of dropped)
|
|
1210
1118
|
this.#notify(key, value, "expired");
|
|
1211
1119
|
return removed;
|
|
1212
1120
|
}
|
|
1213
1121
|
#expireIfDue(key) {
|
|
1214
|
-
const
|
|
1215
|
-
if (!
|
|
1122
|
+
const entry = this.#policy?.entries.get(key);
|
|
1123
|
+
if (!entry || entry.window === 0 || entry.deadline > Date.now())
|
|
1216
1124
|
return false;
|
|
1217
|
-
|
|
1218
|
-
this.#remove(key);
|
|
1219
|
-
this.#stats.expired++;
|
|
1220
|
-
this.#notify(key, value, "expired");
|
|
1125
|
+
this.#expire(entry);
|
|
1221
1126
|
return true;
|
|
1222
1127
|
}
|
|
1128
|
+
#expire(entry) {
|
|
1129
|
+
const value = super.get(entry.key);
|
|
1130
|
+
this.#remove(entry.key);
|
|
1131
|
+
this.#policy.expired++;
|
|
1132
|
+
this.#notify(entry.key, value, "expired");
|
|
1133
|
+
}
|
|
1223
1134
|
#remove(key) {
|
|
1224
|
-
this.#
|
|
1225
|
-
this.#lru.delete(key);
|
|
1135
|
+
this.#forget(key);
|
|
1226
1136
|
super.delete(key);
|
|
1227
1137
|
}
|
|
1138
|
+
#forget(key) {
|
|
1139
|
+
const policy = this.#policy;
|
|
1140
|
+
const entry = policy.entries.get(key);
|
|
1141
|
+
if (!entry)
|
|
1142
|
+
return;
|
|
1143
|
+
if (entry.inLru)
|
|
1144
|
+
this.#unlink(policy, entry);
|
|
1145
|
+
policy.entries.delete(key);
|
|
1146
|
+
}
|
|
1147
|
+
#track(key, value, window, isNew) {
|
|
1148
|
+
const policy = this.#policy;
|
|
1149
|
+
const lru = policy.maxSize !== undefined;
|
|
1150
|
+
let entry = isNew ? undefined : policy.entries.get(key);
|
|
1151
|
+
if (entry)
|
|
1152
|
+
entry.value = value;
|
|
1153
|
+
if (window === undefined) {
|
|
1154
|
+
if (entry && entry.window !== 0) {
|
|
1155
|
+
if (lru)
|
|
1156
|
+
entry = this.#replace(policy, entry, 0, 0);
|
|
1157
|
+
else {
|
|
1158
|
+
this.#forget(key);
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
if (!entry && lru) {
|
|
1163
|
+
entry = this.#create(key, value, 0, 0);
|
|
1164
|
+
policy.entries.set(key, entry);
|
|
1165
|
+
}
|
|
1166
|
+
if (entry)
|
|
1167
|
+
this.#promote(policy, entry);
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
const deadline = Date.now() + window;
|
|
1171
|
+
if (entry && entry.window !== 0) {
|
|
1172
|
+
entry.deadline = deadline;
|
|
1173
|
+
entry.window = window;
|
|
1174
|
+
if (deadline < entry.filed)
|
|
1175
|
+
entry = this.#replace(policy, entry, window, deadline);
|
|
1176
|
+
else {
|
|
1177
|
+
if (entry.inLru)
|
|
1178
|
+
this.#promote(policy, entry);
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
} else if (entry) {
|
|
1182
|
+
entry.window = window;
|
|
1183
|
+
entry.deadline = entry.filed = deadline;
|
|
1184
|
+
} else {
|
|
1185
|
+
entry = this.#create(key, value, window, deadline);
|
|
1186
|
+
policy.entries.set(key, entry);
|
|
1187
|
+
}
|
|
1188
|
+
if (lru)
|
|
1189
|
+
this.#promote(policy, entry);
|
|
1190
|
+
this.#heapPush(entry);
|
|
1191
|
+
if (policy.heap.length > 2 * policy.entries.size + 8)
|
|
1192
|
+
this.#compact();
|
|
1193
|
+
if (policy.timer === undefined || deadline < policy.armedFor)
|
|
1194
|
+
this.#rearm();
|
|
1195
|
+
}
|
|
1196
|
+
#create(key, value, window, deadline) {
|
|
1197
|
+
return {
|
|
1198
|
+
key,
|
|
1199
|
+
value,
|
|
1200
|
+
older: undefined,
|
|
1201
|
+
newer: undefined,
|
|
1202
|
+
inLru: false,
|
|
1203
|
+
window,
|
|
1204
|
+
deadline,
|
|
1205
|
+
filed: deadline
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
#replace(policy, old, window, deadline) {
|
|
1209
|
+
const entry = {
|
|
1210
|
+
...old,
|
|
1211
|
+
window,
|
|
1212
|
+
deadline,
|
|
1213
|
+
filed: deadline
|
|
1214
|
+
};
|
|
1215
|
+
if (old.inLru) {
|
|
1216
|
+
if (old.older)
|
|
1217
|
+
old.older.newer = entry;
|
|
1218
|
+
else
|
|
1219
|
+
policy.oldest = entry;
|
|
1220
|
+
if (old.newer)
|
|
1221
|
+
old.newer.older = entry;
|
|
1222
|
+
else
|
|
1223
|
+
policy.newest = entry;
|
|
1224
|
+
}
|
|
1225
|
+
policy.entries.set(old.key, entry);
|
|
1226
|
+
return entry;
|
|
1227
|
+
}
|
|
1228
|
+
#promote(policy, entry) {
|
|
1229
|
+
if (entry === policy.newest)
|
|
1230
|
+
return;
|
|
1231
|
+
if (entry.inLru)
|
|
1232
|
+
this.#unlink(policy, entry, true);
|
|
1233
|
+
else {
|
|
1234
|
+
entry.inLru = true;
|
|
1235
|
+
policy.lruSize++;
|
|
1236
|
+
}
|
|
1237
|
+
entry.older = policy.newest;
|
|
1238
|
+
entry.newer = undefined;
|
|
1239
|
+
if (policy.newest)
|
|
1240
|
+
policy.newest.newer = entry;
|
|
1241
|
+
else
|
|
1242
|
+
policy.oldest = entry;
|
|
1243
|
+
policy.newest = entry;
|
|
1244
|
+
}
|
|
1245
|
+
#unlink(policy, entry, keepCount = false) {
|
|
1246
|
+
if (entry.older)
|
|
1247
|
+
entry.older.newer = entry.newer;
|
|
1248
|
+
else
|
|
1249
|
+
policy.oldest = entry.newer;
|
|
1250
|
+
if (entry.newer)
|
|
1251
|
+
entry.newer.older = entry.older;
|
|
1252
|
+
else
|
|
1253
|
+
policy.newest = entry.older;
|
|
1254
|
+
entry.older = entry.newer = undefined;
|
|
1255
|
+
if (!keepCount) {
|
|
1256
|
+
entry.inLru = false;
|
|
1257
|
+
policy.lruSize--;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
#derived() {
|
|
1261
|
+
const Species = this.constructor[Symbol.species] ?? Collection;
|
|
1262
|
+
return new Species;
|
|
1263
|
+
}
|
|
1228
1264
|
#notify(key, value, reason) {
|
|
1229
|
-
|
|
1265
|
+
const onEvict = this.#policy?.onEvict;
|
|
1266
|
+
if (!onEvict)
|
|
1230
1267
|
return;
|
|
1231
1268
|
try {
|
|
1232
|
-
|
|
1269
|
+
onEvict(key, value, reason);
|
|
1233
1270
|
} catch {}
|
|
1234
1271
|
}
|
|
1235
1272
|
#enforceCap() {
|
|
1236
|
-
|
|
1273
|
+
const policy = this.#policy;
|
|
1274
|
+
const max = policy.maxSize;
|
|
1275
|
+
if (max === undefined)
|
|
1237
1276
|
return;
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
this.#
|
|
1277
|
+
if (policy.lruSize > max && policy.heap.length > 0 && policy.heap[0].filed <= Date.now())
|
|
1278
|
+
this.purge();
|
|
1279
|
+
while (policy.lruSize > max) {
|
|
1280
|
+
const oldest = policy.oldest;
|
|
1281
|
+
const value = policy.onEvict ? super.get(oldest.key) : undefined;
|
|
1282
|
+
this.#unlink(policy, oldest);
|
|
1283
|
+
policy.entries.delete(oldest.key);
|
|
1284
|
+
super.delete(oldest.key);
|
|
1285
|
+
policy.evicted++;
|
|
1286
|
+
this.#notify(oldest.key, value, "evicted");
|
|
1244
1287
|
}
|
|
1245
1288
|
}
|
|
1246
|
-
#schedule(key, window) {
|
|
1247
|
-
const deadline = Date.now() + window;
|
|
1248
|
-
const expiry = this.#expiry.get(key);
|
|
1249
|
-
if (expiry) {
|
|
1250
|
-
expiry.deadline = deadline;
|
|
1251
|
-
expiry.window = window;
|
|
1252
|
-
if (deadline >= expiry.filed)
|
|
1253
|
-
return;
|
|
1254
|
-
expiry.filed = deadline;
|
|
1255
|
-
} else
|
|
1256
|
-
this.#expiry.set(key, { deadline, window, filed: deadline });
|
|
1257
|
-
this.#heapPush({ key, deadline });
|
|
1258
|
-
if (this.#heap.length > 2 * this.#expiry.size + 8)
|
|
1259
|
-
this.#compact();
|
|
1260
|
-
this.#rearm();
|
|
1261
|
-
}
|
|
1262
1289
|
#nextDeadline() {
|
|
1290
|
+
const policy = this.#policy;
|
|
1263
1291
|
for (;; ) {
|
|
1264
|
-
const top =
|
|
1292
|
+
const top = policy.heap[0];
|
|
1265
1293
|
if (top === undefined)
|
|
1266
1294
|
return Infinity;
|
|
1267
|
-
|
|
1268
|
-
if (!expiry || expiry.filed !== top.deadline) {
|
|
1295
|
+
if (policy.entries.get(top.key) !== top) {
|
|
1269
1296
|
this.#heapPop();
|
|
1270
1297
|
continue;
|
|
1271
1298
|
}
|
|
1272
|
-
if (
|
|
1273
|
-
return top.
|
|
1299
|
+
if (top.deadline === top.filed)
|
|
1300
|
+
return top.filed;
|
|
1274
1301
|
this.#heapPop();
|
|
1275
|
-
|
|
1276
|
-
this.#heapPush(
|
|
1302
|
+
top.filed = top.deadline;
|
|
1303
|
+
this.#heapPush(top);
|
|
1277
1304
|
}
|
|
1278
1305
|
}
|
|
1279
1306
|
#compact() {
|
|
1280
|
-
const
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1307
|
+
const policy = this.#policy;
|
|
1308
|
+
const live = policy.heap.filter((entry) => policy.entries.get(entry.key) === entry);
|
|
1309
|
+
policy.heap.length = 0;
|
|
1310
|
+
for (const entry of live)
|
|
1311
|
+
this.#heapPush(entry);
|
|
1284
1312
|
}
|
|
1285
1313
|
#rearm() {
|
|
1314
|
+
const p = this.#policy;
|
|
1286
1315
|
const deadline = this.#nextDeadline();
|
|
1287
|
-
if (
|
|
1316
|
+
if (p.timer !== undefined && deadline >= p.armedFor)
|
|
1288
1317
|
return;
|
|
1289
|
-
if (
|
|
1290
|
-
clearTimeout(
|
|
1291
|
-
|
|
1292
|
-
|
|
1318
|
+
if (p.timer)
|
|
1319
|
+
clearTimeout(p.timer);
|
|
1320
|
+
p.timer = undefined;
|
|
1321
|
+
p.armedFor = deadline;
|
|
1293
1322
|
if (deadline === Infinity)
|
|
1294
1323
|
return;
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1324
|
+
p.timer = setTimeout(() => {
|
|
1325
|
+
p.timer = undefined;
|
|
1326
|
+
p.armedFor = Infinity;
|
|
1298
1327
|
this.purge();
|
|
1299
1328
|
}, Math.max(0, deadline - Date.now()));
|
|
1300
|
-
|
|
1329
|
+
p.timer.unref?.();
|
|
1301
1330
|
}
|
|
1302
|
-
#heapPush(
|
|
1303
|
-
const heap = this.#heap;
|
|
1304
|
-
heap.
|
|
1305
|
-
|
|
1331
|
+
#heapPush(entry) {
|
|
1332
|
+
const heap = this.#policy.heap;
|
|
1333
|
+
let i = heap.length;
|
|
1334
|
+
heap.push(entry);
|
|
1306
1335
|
while (i > 0) {
|
|
1307
1336
|
const parent = i - 1 >> 1;
|
|
1308
|
-
|
|
1337
|
+
const above = heap[parent];
|
|
1338
|
+
if (above.filed <= entry.filed)
|
|
1309
1339
|
break;
|
|
1310
|
-
|
|
1340
|
+
heap[i] = above;
|
|
1311
1341
|
i = parent;
|
|
1312
1342
|
}
|
|
1343
|
+
heap[i] = entry;
|
|
1313
1344
|
}
|
|
1314
1345
|
#heapPop() {
|
|
1315
|
-
const heap = this.#heap;
|
|
1346
|
+
const heap = this.#policy.heap;
|
|
1316
1347
|
const top = heap[0];
|
|
1317
1348
|
const last = heap.pop();
|
|
1318
1349
|
if (top === undefined || heap.length === 0)
|
|
1319
1350
|
return top;
|
|
1320
|
-
|
|
1321
|
-
for (
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
if (
|
|
1326
|
-
|
|
1327
|
-
if (
|
|
1328
|
-
smallest = right;
|
|
1329
|
-
if (smallest === i)
|
|
1351
|
+
let i = 0;
|
|
1352
|
+
for (;; ) {
|
|
1353
|
+
let child = 2 * i + 1;
|
|
1354
|
+
if (child >= heap.length)
|
|
1355
|
+
break;
|
|
1356
|
+
if (child + 1 < heap.length && heap[child + 1].filed < heap[child].filed)
|
|
1357
|
+
child++;
|
|
1358
|
+
if (heap[child].filed >= last.filed)
|
|
1330
1359
|
break;
|
|
1331
|
-
|
|
1332
|
-
i =
|
|
1360
|
+
heap[i] = heap[child];
|
|
1361
|
+
i = child;
|
|
1333
1362
|
}
|
|
1363
|
+
heap[i] = last;
|
|
1334
1364
|
return top;
|
|
1335
1365
|
}
|
|
1336
1366
|
first() {
|
|
@@ -1362,8 +1392,26 @@ class Collection extends Map {
|
|
|
1362
1392
|
}
|
|
1363
1393
|
return;
|
|
1364
1394
|
}
|
|
1395
|
+
findLast(predicate) {
|
|
1396
|
+
const entries = [...this];
|
|
1397
|
+
for (let i = entries.length - 1;i >= 0; i--) {
|
|
1398
|
+
const [key, value] = entries[i];
|
|
1399
|
+
if (predicate(value, key, this))
|
|
1400
|
+
return value;
|
|
1401
|
+
}
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
findLastKey(predicate) {
|
|
1405
|
+
const entries = [...this];
|
|
1406
|
+
for (let i = entries.length - 1;i >= 0; i--) {
|
|
1407
|
+
const [key, value] = entries[i];
|
|
1408
|
+
if (predicate(value, key, this))
|
|
1409
|
+
return key;
|
|
1410
|
+
}
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1365
1413
|
filter(predicate) {
|
|
1366
|
-
const result =
|
|
1414
|
+
const result = this.#derived();
|
|
1367
1415
|
for (const [key, value] of this) {
|
|
1368
1416
|
if (predicate(value, key, this))
|
|
1369
1417
|
result.set(key, value);
|
|
@@ -1407,7 +1455,7 @@ class Collection extends Map {
|
|
|
1407
1455
|
return [...this.entries()];
|
|
1408
1456
|
}
|
|
1409
1457
|
clone() {
|
|
1410
|
-
const copy =
|
|
1458
|
+
const copy = this.#derived();
|
|
1411
1459
|
for (const [key, value] of this)
|
|
1412
1460
|
copy.set(key, value);
|
|
1413
1461
|
return copy;
|
|
@@ -1462,7 +1510,7 @@ class Collection extends Map {
|
|
|
1462
1510
|
return result;
|
|
1463
1511
|
}
|
|
1464
1512
|
intersection(other) {
|
|
1465
|
-
const result =
|
|
1513
|
+
const result = this.#derived();
|
|
1466
1514
|
for (const [key, value] of this) {
|
|
1467
1515
|
if (other.has(key))
|
|
1468
1516
|
result.set(key, value);
|
|
@@ -1470,7 +1518,7 @@ class Collection extends Map {
|
|
|
1470
1518
|
return result;
|
|
1471
1519
|
}
|
|
1472
1520
|
difference(other) {
|
|
1473
|
-
const result =
|
|
1521
|
+
const result = this.#derived();
|
|
1474
1522
|
for (const [key, value] of this) {
|
|
1475
1523
|
if (!other.has(key))
|
|
1476
1524
|
result.set(key, value);
|
|
@@ -1478,8 +1526,8 @@ class Collection extends Map {
|
|
|
1478
1526
|
return result;
|
|
1479
1527
|
}
|
|
1480
1528
|
partition(predicate) {
|
|
1481
|
-
const pass =
|
|
1482
|
-
const fail =
|
|
1529
|
+
const pass = this.#derived();
|
|
1530
|
+
const fail = this.#derived();
|
|
1483
1531
|
for (const [key, value] of this) {
|
|
1484
1532
|
if (predicate(value, key, this))
|
|
1485
1533
|
pass.set(key, value);
|
|
@@ -1488,6 +1536,81 @@ class Collection extends Map {
|
|
|
1488
1536
|
}
|
|
1489
1537
|
return [pass, fail];
|
|
1490
1538
|
}
|
|
1539
|
+
symmetricDifference(other) {
|
|
1540
|
+
const result = this.#derived();
|
|
1541
|
+
for (const [key, value] of this)
|
|
1542
|
+
if (!other.has(key))
|
|
1543
|
+
result.set(key, value);
|
|
1544
|
+
for (const [key, value] of other)
|
|
1545
|
+
if (!this.has(key))
|
|
1546
|
+
result.set(key, value);
|
|
1547
|
+
return result;
|
|
1548
|
+
}
|
|
1549
|
+
concat(...collections) {
|
|
1550
|
+
const result = this.clone();
|
|
1551
|
+
for (const collection of collections)
|
|
1552
|
+
for (const [key, value] of collection)
|
|
1553
|
+
result.set(key, value);
|
|
1554
|
+
return result;
|
|
1555
|
+
}
|
|
1556
|
+
merge(other, whenInSelf, whenInOther, whenInBoth) {
|
|
1557
|
+
const result = this.#derived();
|
|
1558
|
+
const decide = (key, kept) => {
|
|
1559
|
+
if (kept.keep)
|
|
1560
|
+
result.set(key, kept.value);
|
|
1561
|
+
};
|
|
1562
|
+
for (const [key, value] of this) {
|
|
1563
|
+
decide(key, other.has(key) ? whenInBoth(value, peekOf(other, key), key) : whenInSelf(value, key));
|
|
1564
|
+
}
|
|
1565
|
+
for (const [key, value] of other)
|
|
1566
|
+
if (!this.has(key))
|
|
1567
|
+
decide(key, whenInOther(value, key));
|
|
1568
|
+
return result;
|
|
1569
|
+
}
|
|
1570
|
+
equals(other) {
|
|
1571
|
+
if (!other)
|
|
1572
|
+
return false;
|
|
1573
|
+
if (other === this)
|
|
1574
|
+
return true;
|
|
1575
|
+
if (this.size !== other.size)
|
|
1576
|
+
return false;
|
|
1577
|
+
for (const [key, value] of this) {
|
|
1578
|
+
if (!other.has(key))
|
|
1579
|
+
return false;
|
|
1580
|
+
if (value !== peekOf(other, key))
|
|
1581
|
+
return false;
|
|
1582
|
+
}
|
|
1583
|
+
return true;
|
|
1584
|
+
}
|
|
1585
|
+
mapValues(transform) {
|
|
1586
|
+
const result = this.#derived();
|
|
1587
|
+
for (const [key, value] of this)
|
|
1588
|
+
result.set(key, transform(value, key, this));
|
|
1589
|
+
return result;
|
|
1590
|
+
}
|
|
1591
|
+
toReversed() {
|
|
1592
|
+
const result = this.#derived();
|
|
1593
|
+
const entries = [...this];
|
|
1594
|
+
for (let i = entries.length - 1;i >= 0; i--)
|
|
1595
|
+
result.set(entries[i][0], entries[i][1]);
|
|
1596
|
+
return result;
|
|
1597
|
+
}
|
|
1598
|
+
toSorted(comparator) {
|
|
1599
|
+
return this.sorted(comparator);
|
|
1600
|
+
}
|
|
1601
|
+
static groupBy(items, keySelector) {
|
|
1602
|
+
const groups = new Collection;
|
|
1603
|
+
let index = 0;
|
|
1604
|
+
for (const item of items)
|
|
1605
|
+
groups.ensure(keySelector(item, index++), () => []).push(item);
|
|
1606
|
+
return groups;
|
|
1607
|
+
}
|
|
1608
|
+
static combineEntries(entries, combine) {
|
|
1609
|
+
const result = new Collection;
|
|
1610
|
+
for (const [key, value] of entries)
|
|
1611
|
+
result.set(key, result.has(key) ? combine(result.get(key), value, key) : value);
|
|
1612
|
+
return result;
|
|
1613
|
+
}
|
|
1491
1614
|
tap(fn) {
|
|
1492
1615
|
fn(this);
|
|
1493
1616
|
return this;
|
|
@@ -1506,6 +1629,13 @@ class Collection extends Map {
|
|
|
1506
1629
|
acc = fn(acc, value, key, this);
|
|
1507
1630
|
return acc;
|
|
1508
1631
|
}
|
|
1632
|
+
reduceRight(fn, initialValue) {
|
|
1633
|
+
const entries = [...this];
|
|
1634
|
+
let acc = initialValue;
|
|
1635
|
+
for (let i = entries.length - 1;i >= 0; i--)
|
|
1636
|
+
acc = fn(acc, entries[i][1], entries[i][0], this);
|
|
1637
|
+
return acc;
|
|
1638
|
+
}
|
|
1509
1639
|
sorted(comparator) {
|
|
1510
1640
|
const decorated = [...this.entries()].map((entry, index) => ({
|
|
1511
1641
|
entry,
|
|
@@ -1516,22 +1646,34 @@ class Collection extends Map {
|
|
|
1516
1646
|
const comparison = comparator(x.entry[1], y.entry[1], x.entry[0], y.entry[0]);
|
|
1517
1647
|
return comparison !== 0 ? comparison : x.index - y.index;
|
|
1518
1648
|
});
|
|
1519
|
-
const result =
|
|
1649
|
+
const result = this.#derived();
|
|
1520
1650
|
for (const { entry } of decorated)
|
|
1521
1651
|
result.set(entry[0], entry[1]);
|
|
1522
1652
|
return result;
|
|
1523
1653
|
}
|
|
1524
|
-
random() {
|
|
1525
|
-
|
|
1526
|
-
|
|
1654
|
+
random(amount) {
|
|
1655
|
+
if (amount !== undefined)
|
|
1656
|
+
return sample([...this.values()], amount);
|
|
1657
|
+
const size = this.size;
|
|
1658
|
+
if (size === 0)
|
|
1527
1659
|
return;
|
|
1528
|
-
|
|
1660
|
+
let index = Math.floor(Math.random() * size);
|
|
1661
|
+
for (const value of this.values())
|
|
1662
|
+
if (index-- === 0)
|
|
1663
|
+
return value;
|
|
1664
|
+
return;
|
|
1529
1665
|
}
|
|
1530
|
-
randomKey() {
|
|
1531
|
-
|
|
1532
|
-
|
|
1666
|
+
randomKey(amount) {
|
|
1667
|
+
if (amount !== undefined)
|
|
1668
|
+
return sample([...this.keys()], amount);
|
|
1669
|
+
const size = this.size;
|
|
1670
|
+
if (size === 0)
|
|
1533
1671
|
return;
|
|
1534
|
-
|
|
1672
|
+
let index = Math.floor(Math.random() * size);
|
|
1673
|
+
for (const key of this.keys())
|
|
1674
|
+
if (index-- === 0)
|
|
1675
|
+
return key;
|
|
1676
|
+
return;
|
|
1535
1677
|
}
|
|
1536
1678
|
at(index) {
|
|
1537
1679
|
const arr = [...this.values()];
|
|
@@ -1655,7 +1797,7 @@ class ResourceManager extends Manager {
|
|
|
1655
1797
|
// packages/rest/package.json
|
|
1656
1798
|
var package_default = {
|
|
1657
1799
|
name: "@lunibee/rest",
|
|
1658
|
-
version: "0.2.
|
|
1800
|
+
version: "0.2.4",
|
|
1659
1801
|
type: "module",
|
|
1660
1802
|
module: "./src/index.ts",
|
|
1661
1803
|
types: "./src/index.ts",
|
|
@@ -1736,7 +1878,7 @@ function kindFromStatus(status) {
|
|
|
1736
1878
|
return "client";
|
|
1737
1879
|
}
|
|
1738
1880
|
function redactPath(path) {
|
|
1739
|
-
return path.replace(/^(\/webhooks\/[^/?]+\/)[^/?]
|
|
1881
|
+
return path.replace(/^(\/webhooks\/[^/?]+\/)[^/?]+/i, "$1:token").replace(/^(\/interactions\/[^/?]+\/)[^/?]+/i, "$1:token");
|
|
1740
1882
|
}
|
|
1741
1883
|
var HINTS = {
|
|
1742
1884
|
50001: "The bot cannot see this resource: check that it is in the guild and has View Channel there.",
|
|
@@ -1795,19 +1937,23 @@ async function abortable(promise, signal, path) {
|
|
|
1795
1937
|
}
|
|
1796
1938
|
|
|
1797
1939
|
// packages/rest/src/route.ts
|
|
1940
|
+
import { createHash } from "crypto";
|
|
1798
1941
|
function normalizeRoutePath(path) {
|
|
1799
1942
|
const queryIndex = path.indexOf("?");
|
|
1800
1943
|
const routePath = queryIndex === -1 ? path : path.slice(0, queryIndex);
|
|
1801
|
-
return routePath.replace(/\/\d+(?=\/|$)/g, "/:id");
|
|
1944
|
+
return redactPath(routePath).replace(/\/\d+(?=\/|$)/g, "/:id");
|
|
1802
1945
|
}
|
|
1803
1946
|
function majorParameter(path) {
|
|
1804
|
-
const match = /^\/(channels|guilds|webhooks)\/(\d+)(?:\/([^/?]+))
|
|
1947
|
+
const match = /^\/(channels|guilds|webhooks)\/(\d+)(?:\/([^/?]+))?/i.exec(path);
|
|
1805
1948
|
if (!match)
|
|
1806
1949
|
return "@none";
|
|
1807
|
-
if (match[1] === "webhooks" && match[3] !== undefined)
|
|
1808
|
-
return `${match[2]}:${match[3]}`;
|
|
1950
|
+
if (match[1].toLowerCase() === "webhooks" && match[3] !== undefined)
|
|
1951
|
+
return `${match[2]}:${tokenDigest(match[3])}`;
|
|
1809
1952
|
return match[2];
|
|
1810
1953
|
}
|
|
1954
|
+
function tokenDigest(token) {
|
|
1955
|
+
return createHash("sha256").update(token).digest("hex").slice(0, 16);
|
|
1956
|
+
}
|
|
1811
1957
|
function scopeBucket(hashOrRoute, major) {
|
|
1812
1958
|
return `${hashOrRoute}|${major}`;
|
|
1813
1959
|
}
|
|
@@ -2049,6 +2195,9 @@ var Routes = {
|
|
|
2049
2195
|
user: () => "/users/@me",
|
|
2050
2196
|
userById: (userId) => `/users/${snowflake(userId, "User ID")}`,
|
|
2051
2197
|
guild: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}`,
|
|
2198
|
+
currentUserGuild: (guildId) => `/users/@me/guilds/${snowflake(guildId, "Guild ID")}`,
|
|
2199
|
+
sticker: (stickerId) => `/stickers/${snowflake(stickerId, "Sticker ID")}`,
|
|
2200
|
+
messageReactionUser: (channelId, messageId, emoji, userId) => `${Routes.messageReactions(channelId, messageId, emoji)}/${snowflake(userId, "User ID")}`,
|
|
2052
2201
|
guildPreview: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/preview`,
|
|
2053
2202
|
guildActiveThreads: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/threads/active`,
|
|
2054
2203
|
guildWebhooks: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/webhooks`,
|
|
@@ -2310,7 +2459,7 @@ class WebhookClient {
|
|
|
2310
2459
|
#rest;
|
|
2311
2460
|
constructor(options, restOptions) {
|
|
2312
2461
|
if (options.url) {
|
|
2313
|
-
const match = options.url.match(
|
|
2462
|
+
const match = options.url.match(/^https:\/\/(?:(?:ptb|canary)\.)?discord(?:app)?\.com\/api(?:\/v\d+)?\/webhooks\/(\d{1,20})\/([A-Za-z0-9_-]+)\/?(?:[?#].*)?$/);
|
|
2314
2463
|
if (!match)
|
|
2315
2464
|
throw new Error("Invalid Discord webhook URL format.");
|
|
2316
2465
|
this.id = match[1];
|
|
@@ -2325,13 +2474,20 @@ class WebhookClient {
|
|
|
2325
2474
|
}
|
|
2326
2475
|
async send(options) {
|
|
2327
2476
|
const payload = typeof options === "string" ? { content: options } : options;
|
|
2328
|
-
const { thread_id, ...body } = payload;
|
|
2329
|
-
const
|
|
2477
|
+
const { thread_id, files, ...body } = payload;
|
|
2478
|
+
const params = new URLSearchParams({ wait: "true" });
|
|
2479
|
+
if (thread_id)
|
|
2480
|
+
params.set("thread_id", String(thread_id));
|
|
2481
|
+
const query = `?${params}`;
|
|
2330
2482
|
const formattedEmbeds = body.embeds?.map((e) => ("toJSON" in e) ? e.toJSON() : e);
|
|
2331
|
-
|
|
2483
|
+
const formattedComponents = body.components?.map((c) => ("toJSON" in c) ? c.toJSON() : c);
|
|
2484
|
+
const path = `${Routes.webhook(this.id, this.token)}${query}`;
|
|
2485
|
+
const json = {
|
|
2332
2486
|
...body,
|
|
2333
|
-
embeds: formattedEmbeds
|
|
2334
|
-
|
|
2487
|
+
embeds: formattedEmbeds,
|
|
2488
|
+
components: formattedComponents
|
|
2489
|
+
};
|
|
2490
|
+
return files?.length ? this.#rest.postWithFiles(path, json, files) : this.#rest.post(path, json);
|
|
2335
2491
|
}
|
|
2336
2492
|
async editMessage(messageId, options) {
|
|
2337
2493
|
const payload = typeof options === "string" ? { content: options } : options;
|
|
@@ -2346,6 +2502,22 @@ class WebhookClient {
|
|
|
2346
2502
|
var LIBRARY_VERSION = package_default.version;
|
|
2347
2503
|
var LIBRARY_URL = "https://github.com/Ekretos/lunibee";
|
|
2348
2504
|
var USER_AGENT = `DiscordBot (${LIBRARY_URL}, ${LIBRARY_VERSION})`;
|
|
2505
|
+
function assertSafePath(path) {
|
|
2506
|
+
const end = path.search(/[?#]/);
|
|
2507
|
+
const pathname = end === -1 ? path : path.slice(0, end);
|
|
2508
|
+
if (pathname.includes("\\"))
|
|
2509
|
+
throw new TypeError("REST paths must not contain backslashes.");
|
|
2510
|
+
for (const segment of pathname.split("/")) {
|
|
2511
|
+
let decoded;
|
|
2512
|
+
try {
|
|
2513
|
+
decoded = decodeURIComponent(segment);
|
|
2514
|
+
} catch {
|
|
2515
|
+
throw new TypeError("REST path has malformed percent-encoding.");
|
|
2516
|
+
}
|
|
2517
|
+
if (decoded === "." || decoded === "..")
|
|
2518
|
+
throw new TypeError("REST paths must not contain '.' or '..' segments.");
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2349
2521
|
var REQUEST_DATA_KEYS = new Set([
|
|
2350
2522
|
"body",
|
|
2351
2523
|
"files",
|
|
@@ -2430,6 +2602,7 @@ class REST {
|
|
|
2430
2602
|
throw new TypeError("REST method is required.");
|
|
2431
2603
|
if (!path.startsWith("/"))
|
|
2432
2604
|
throw new TypeError("REST paths must start with '/'.");
|
|
2605
|
+
assertSafePath(path);
|
|
2433
2606
|
const route = createRouteKey(method, path);
|
|
2434
2607
|
const files = options.files;
|
|
2435
2608
|
if (files && files.length > 0 && !(body instanceof FormData))
|
|
@@ -2517,13 +2690,19 @@ class REST {
|
|
|
2517
2690
|
#headers(body, options) {
|
|
2518
2691
|
const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
|
|
2519
2692
|
const headers = { ...options.headers };
|
|
2693
|
+
const set = (name, value) => {
|
|
2694
|
+
for (const key of Object.keys(headers))
|
|
2695
|
+
if (key.toLowerCase() === name.toLowerCase())
|
|
2696
|
+
delete headers[key];
|
|
2697
|
+
headers[name] = value;
|
|
2698
|
+
};
|
|
2520
2699
|
if (options.auth !== false && this.#token)
|
|
2521
|
-
|
|
2522
|
-
|
|
2700
|
+
set("Authorization", `Bot ${this.#token}`);
|
|
2701
|
+
set("User-Agent", USER_AGENT);
|
|
2523
2702
|
if (options.reason !== undefined)
|
|
2524
|
-
|
|
2703
|
+
set("X-Audit-Log-Reason", encodeURIComponent(options.reason));
|
|
2525
2704
|
if (!isFormData)
|
|
2526
|
-
|
|
2705
|
+
set("Content-Type", "application/json");
|
|
2527
2706
|
return headers;
|
|
2528
2707
|
}
|
|
2529
2708
|
#encodeBody(body) {
|
|
@@ -2599,7 +2778,7 @@ function cdnURL(path, hash, options = {}) {
|
|
|
2599
2778
|
const isAnimated = hash.startsWith("a_") && !options.forceStatic;
|
|
2600
2779
|
const ext = options.extension ?? (isAnimated ? "gif" : "png");
|
|
2601
2780
|
const size = options.size ? `?size=${options.size}` : "";
|
|
2602
|
-
return `${CDN_BASE}${path}/${hash}.${ext}${size}`;
|
|
2781
|
+
return `${CDN_BASE}${path}/${encodeURIComponent(hash)}.${ext}${size}`;
|
|
2603
2782
|
}
|
|
2604
2783
|
|
|
2605
2784
|
class User extends BaseStructure {
|
|
@@ -2889,10 +3068,10 @@ class GuildMember {
|
|
|
2889
3068
|
get permissions() {
|
|
2890
3069
|
if (this.#suppliedPermissions)
|
|
2891
3070
|
return this.#suppliedPermissions;
|
|
2892
|
-
return new PermissionsBitField(this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds) ?? 0n);
|
|
3071
|
+
return new PermissionsBitField(this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds, undefined, this.timedOutUntil) ?? 0n);
|
|
2893
3072
|
}
|
|
2894
3073
|
permissionsIn(channelId) {
|
|
2895
|
-
const computed = this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds, channelId);
|
|
3074
|
+
const computed = this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds, channelId, this.timedOutUntil);
|
|
2896
3075
|
return computed ? new PermissionsBitField(computed) : null;
|
|
2897
3076
|
}
|
|
2898
3077
|
#action(name) {
|
|
@@ -4343,7 +4522,7 @@ class UserManager extends ResourceManager {
|
|
|
4343
4522
|
return this.upsert(new User(data));
|
|
4344
4523
|
}
|
|
4345
4524
|
async leaveGuild(guildId) {
|
|
4346
|
-
await this.#rest.delete(
|
|
4525
|
+
await this.#rest.delete(Routes.currentUserGuild(guildId));
|
|
4347
4526
|
}
|
|
4348
4527
|
async createDM(userId) {
|
|
4349
4528
|
return this.#rest.post("/users/@me/channels", {
|
|
@@ -4632,20 +4811,15 @@ class RoleManager extends ResourceManager {
|
|
|
4632
4811
|
}
|
|
4633
4812
|
async create(options) {
|
|
4634
4813
|
const { reason, ...payload } = options;
|
|
4635
|
-
const data = await this.#rest.post(Routes.guildRoles(this.guildId), {
|
|
4636
|
-
|
|
4637
|
-
permissions: payload.permissions !== undefined ? String(payload.permissions) : undefined
|
|
4638
|
-
}, { reason });
|
|
4639
|
-
const role = new Role(data);
|
|
4640
|
-
this.set(role.id, role);
|
|
4641
|
-
return role;
|
|
4814
|
+
const data = await this.#rest.post(Routes.guildRoles(this.guildId), rolePayload(payload), { reason });
|
|
4815
|
+
return this.#store(data);
|
|
4642
4816
|
}
|
|
4643
4817
|
async edit(roleId, options) {
|
|
4644
4818
|
const { reason, ...payload } = options;
|
|
4645
|
-
const data = await this.#rest.patch(Routes.guildRole(this.guildId, roleId), {
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4819
|
+
const data = await this.#rest.patch(Routes.guildRole(this.guildId, roleId), rolePayload(payload), { reason });
|
|
4820
|
+
return this.#store(data);
|
|
4821
|
+
}
|
|
4822
|
+
#store(data) {
|
|
4649
4823
|
const role = new Role(data);
|
|
4650
4824
|
this.set(role.id, role);
|
|
4651
4825
|
return role;
|
|
@@ -4668,6 +4842,13 @@ class RoleManager extends ResourceManager {
|
|
|
4668
4842
|
return this.remove(roleId);
|
|
4669
4843
|
}
|
|
4670
4844
|
}
|
|
4845
|
+
function rolePayload(options) {
|
|
4846
|
+
const { permissions, ...rest } = options;
|
|
4847
|
+
return {
|
|
4848
|
+
...rest,
|
|
4849
|
+
permissions: permissions !== undefined ? String(permissions) : undefined
|
|
4850
|
+
};
|
|
4851
|
+
}
|
|
4671
4852
|
|
|
4672
4853
|
// packages/managers/src/guild-resources.ts
|
|
4673
4854
|
function withQuery2(path, params) {
|
|
@@ -5304,7 +5485,7 @@ class ChannelManager extends Manager {
|
|
|
5304
5485
|
await this.#rest.delete(`${Routes.messageReactions(channelId, messageId, emoji)}/@me`);
|
|
5305
5486
|
}
|
|
5306
5487
|
async removeReaction(channelId, messageId, emoji, userId) {
|
|
5307
|
-
await this.#rest.delete(
|
|
5488
|
+
await this.#rest.delete(Routes.messageReactionUser(channelId, messageId, emoji, userId));
|
|
5308
5489
|
}
|
|
5309
5490
|
async removeAllReactions(channelId, messageId) {
|
|
5310
5491
|
await this.#rest.delete(Routes.messageReactionsAll(channelId, messageId));
|
|
@@ -5427,7 +5608,26 @@ class GatewaySession {
|
|
|
5427
5608
|
return resume ? { type: "resume", ...resume } : { type: "identify" };
|
|
5428
5609
|
}
|
|
5429
5610
|
connectURL(fallback) {
|
|
5430
|
-
|
|
5611
|
+
const resume = this.resumeInfo()?.resumeURL;
|
|
5612
|
+
return resume !== undefined && isTrustedGatewayURL(resume, fallback) ? resume : fallback;
|
|
5613
|
+
}
|
|
5614
|
+
}
|
|
5615
|
+
function isTrustedGatewayURL(url, fallback) {
|
|
5616
|
+
let parsed;
|
|
5617
|
+
try {
|
|
5618
|
+
parsed = new URL(url);
|
|
5619
|
+
} catch {
|
|
5620
|
+
return false;
|
|
5621
|
+
}
|
|
5622
|
+
if (parsed.protocol !== "wss:" || parsed.username || parsed.password)
|
|
5623
|
+
return false;
|
|
5624
|
+
const host = parsed.hostname.toLowerCase();
|
|
5625
|
+
if (host === "discord.gg" || host.endsWith(".discord.gg"))
|
|
5626
|
+
return true;
|
|
5627
|
+
try {
|
|
5628
|
+
return host === new URL(fallback).hostname.toLowerCase();
|
|
5629
|
+
} catch {
|
|
5630
|
+
return false;
|
|
5431
5631
|
}
|
|
5432
5632
|
}
|
|
5433
5633
|
|
|
@@ -5703,12 +5903,15 @@ class PlainTextDecoder {
|
|
|
5703
5903
|
|
|
5704
5904
|
class ZlibStreamDecoder {
|
|
5705
5905
|
#create;
|
|
5906
|
+
#maxFrameBytes;
|
|
5706
5907
|
#inflate;
|
|
5707
5908
|
#chunks = [];
|
|
5909
|
+
#size = 0;
|
|
5708
5910
|
#failure;
|
|
5709
5911
|
#pendingReject;
|
|
5710
|
-
constructor(create = () => createInflate()) {
|
|
5912
|
+
constructor(create = () => createInflate(), maxFrameBytes = 64 * 1024 * 1024) {
|
|
5711
5913
|
this.#create = create;
|
|
5914
|
+
this.#maxFrameBytes = maxFrameBytes;
|
|
5712
5915
|
}
|
|
5713
5916
|
push(data) {
|
|
5714
5917
|
if (typeof data === "string")
|
|
@@ -5727,6 +5930,7 @@ class ZlibStreamDecoder {
|
|
|
5727
5930
|
await this.#awaiting((settle) => inflate.flush(zlibConstants.Z_SYNC_FLUSH, () => settle()));
|
|
5728
5931
|
const parts = this.#chunks;
|
|
5729
5932
|
this.#chunks = [];
|
|
5933
|
+
this.#size = 0;
|
|
5730
5934
|
if (parts.length === 0)
|
|
5731
5935
|
return [];
|
|
5732
5936
|
const total = parts.reduce((size, part) => size + part.length, 0);
|
|
@@ -5742,6 +5946,7 @@ class ZlibStreamDecoder {
|
|
|
5742
5946
|
const inflate = this.#inflate;
|
|
5743
5947
|
this.#inflate = undefined;
|
|
5744
5948
|
this.#chunks = [];
|
|
5949
|
+
this.#size = 0;
|
|
5745
5950
|
this.#failure = undefined;
|
|
5746
5951
|
this.#pendingReject = undefined;
|
|
5747
5952
|
if (!inflate)
|
|
@@ -5769,7 +5974,17 @@ class ZlibStreamDecoder {
|
|
|
5769
5974
|
}
|
|
5770
5975
|
#open() {
|
|
5771
5976
|
const inflate = this.#create();
|
|
5772
|
-
inflate.on("data", (chunk) =>
|
|
5977
|
+
inflate.on("data", (chunk) => {
|
|
5978
|
+
if (this.#failure)
|
|
5979
|
+
return;
|
|
5980
|
+
this.#size += chunk.length;
|
|
5981
|
+
if (this.#size > this.#maxFrameBytes) {
|
|
5982
|
+
this.#chunks = [];
|
|
5983
|
+
inflate.emit("error", new Error(`Gateway frame inflated past ${this.#maxFrameBytes} bytes.`));
|
|
5984
|
+
return;
|
|
5985
|
+
}
|
|
5986
|
+
this.#chunks.push(chunk);
|
|
5987
|
+
});
|
|
5773
5988
|
inflate.on("error", (error) => {
|
|
5774
5989
|
this.#failure = error;
|
|
5775
5990
|
const reject = this.#pendingReject;
|
|
@@ -6012,9 +6227,9 @@ function classifyPayload(payload) {
|
|
|
6012
6227
|
}
|
|
6013
6228
|
function identifyPayload(options) {
|
|
6014
6229
|
const props = options.properties ?? {};
|
|
6015
|
-
const os = props.os ??
|
|
6016
|
-
const browser = props.browser ?? "
|
|
6017
|
-
const device = props.device ?? "
|
|
6230
|
+
const os = props.os ?? process.platform;
|
|
6231
|
+
const browser = props.browser ?? "Lunibee";
|
|
6232
|
+
const device = props.device ?? "Lunibee";
|
|
6018
6233
|
return {
|
|
6019
6234
|
op: GatewayOpcodes.Identify,
|
|
6020
6235
|
d: {
|
|
@@ -6131,9 +6346,9 @@ class Gateway {
|
|
|
6131
6346
|
heartbeatAckTimeout: 1e4,
|
|
6132
6347
|
zombieTimeout: 30000,
|
|
6133
6348
|
properties: {
|
|
6134
|
-
os:
|
|
6135
|
-
browser: "
|
|
6136
|
-
device: "
|
|
6349
|
+
os: process.platform,
|
|
6350
|
+
browser: "Lunibee",
|
|
6351
|
+
device: "Lunibee"
|
|
6137
6352
|
},
|
|
6138
6353
|
presence: {
|
|
6139
6354
|
status: "online",
|
|
@@ -6449,14 +6664,12 @@ class Gateway {
|
|
|
6449
6664
|
|
|
6450
6665
|
// packages/core/src/index.ts
|
|
6451
6666
|
class EventEmitter2 {
|
|
6452
|
-
#listeners =
|
|
6667
|
+
#listeners = {};
|
|
6668
|
+
redactSecrets = (text) => text;
|
|
6453
6669
|
on(event, listener) {
|
|
6454
6670
|
if (typeof listener !== "function")
|
|
6455
6671
|
throw new TypeError("Event listener must be a function.");
|
|
6456
|
-
|
|
6457
|
-
if (!listeners)
|
|
6458
|
-
this.#listeners.set(event, listeners = new Set);
|
|
6459
|
-
listeners.add(listener);
|
|
6672
|
+
(this.#listeners[event] ??= new Set).add(listener);
|
|
6460
6673
|
return this;
|
|
6461
6674
|
}
|
|
6462
6675
|
once(event, listener) {
|
|
@@ -6467,7 +6680,7 @@ class EventEmitter2 {
|
|
|
6467
6680
|
return this.on(event, wrapped);
|
|
6468
6681
|
}
|
|
6469
6682
|
off(event, listener) {
|
|
6470
|
-
this.#listeners
|
|
6683
|
+
this.#listeners[event]?.delete(listener);
|
|
6471
6684
|
return this;
|
|
6472
6685
|
}
|
|
6473
6686
|
removeListener(event, listener) {
|
|
@@ -6475,13 +6688,13 @@ class EventEmitter2 {
|
|
|
6475
6688
|
}
|
|
6476
6689
|
removeAllListeners(event) {
|
|
6477
6690
|
if (event === undefined)
|
|
6478
|
-
this.#listeners
|
|
6691
|
+
this.#listeners = {};
|
|
6479
6692
|
else
|
|
6480
|
-
this.#listeners
|
|
6693
|
+
delete this.#listeners[event];
|
|
6481
6694
|
return this;
|
|
6482
6695
|
}
|
|
6483
6696
|
emit(event, ...args) {
|
|
6484
|
-
const listeners = this.#listeners
|
|
6697
|
+
const listeners = this.#listeners[event];
|
|
6485
6698
|
if (!listeners?.size)
|
|
6486
6699
|
return false;
|
|
6487
6700
|
for (const listener of [...listeners]) {
|
|
@@ -6497,28 +6710,27 @@ class EventEmitter2 {
|
|
|
6497
6710
|
}
|
|
6498
6711
|
#handleError(event, error) {
|
|
6499
6712
|
const normalized = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
6500
|
-
const
|
|
6501
|
-
|
|
6502
|
-
];
|
|
6713
|
+
const errorListeners = this.#listeners["error" /* Error */];
|
|
6714
|
+
const listeners = event === "error" /* Error */ ? [] : [...errorListeners ?? []];
|
|
6503
6715
|
if (listeners.length === 0)
|
|
6504
|
-
return warnListenerError(event, normalized);
|
|
6716
|
+
return warnListenerError(event, normalized, this.redactSecrets);
|
|
6505
6717
|
for (const listener of listeners) {
|
|
6506
6718
|
try {
|
|
6507
6719
|
const result = listener(normalized);
|
|
6508
6720
|
if (result && typeof result.then === "function")
|
|
6509
|
-
Promise.resolve(result).catch((failure) => warnListenerError("error" /* Error */, failure));
|
|
6721
|
+
Promise.resolve(result).catch((failure) => warnListenerError("error" /* Error */, failure, this.redactSecrets));
|
|
6510
6722
|
} catch (failure) {
|
|
6511
|
-
warnListenerError("error" /* Error */, failure);
|
|
6723
|
+
warnListenerError("error" /* Error */, failure, this.redactSecrets);
|
|
6512
6724
|
}
|
|
6513
6725
|
}
|
|
6514
6726
|
}
|
|
6515
6727
|
}
|
|
6516
|
-
function warnListenerError(event, error) {
|
|
6728
|
+
function warnListenerError(event, error, redact = (text) => text) {
|
|
6517
6729
|
const failure = error instanceof Error ? error : new Error(String(error));
|
|
6518
|
-
process.emitWarning(`A "${String(event)}" listener threw and no error listener handled it: ${failure.message}
|
|
6730
|
+
process.emitWarning(redact(`A "${String(event)}" listener threw and no error listener handled it: ${failure.message}`), {
|
|
6519
6731
|
type: "LunibeeWarning",
|
|
6520
6732
|
code: "LUNIBEE_UNHANDLED_LISTENER_ERROR",
|
|
6521
|
-
detail: failure.stack
|
|
6733
|
+
detail: failure.stack === undefined ? undefined : redact(failure.stack)
|
|
6522
6734
|
});
|
|
6523
6735
|
}
|
|
6524
6736
|
|
|
@@ -6540,6 +6752,10 @@ class Client extends EventEmitter2 {
|
|
|
6540
6752
|
user;
|
|
6541
6753
|
readyAt;
|
|
6542
6754
|
state = "idle";
|
|
6755
|
+
redactSecrets = (text) => {
|
|
6756
|
+
const token = this.options.token;
|
|
6757
|
+
return token && token.length >= 8 ? text.split(token).join("[token]") : text;
|
|
6758
|
+
};
|
|
6543
6759
|
get token() {
|
|
6544
6760
|
return this.state === "destroyed" ? null : this.options.token ?? null;
|
|
6545
6761
|
}
|
|
@@ -6586,7 +6802,22 @@ class Client extends EventEmitter2 {
|
|
|
6586
6802
|
this.stageInstances = new StageInstanceManager(this.rest);
|
|
6587
6803
|
const placeholderAppCommands = new ApplicationCommandManager(this.rest, "0");
|
|
6588
6804
|
this.application = { commands: placeholderAppCommands };
|
|
6589
|
-
this.#resourceContext =
|
|
6805
|
+
this.#resourceContext = this.#createResourceContext();
|
|
6806
|
+
this.guilds.attachContext(this.#resourceContext);
|
|
6807
|
+
this.#gateway = new Gateway({
|
|
6808
|
+
token: options.token,
|
|
6809
|
+
intents: options.intents,
|
|
6810
|
+
...options.gateway
|
|
6811
|
+
});
|
|
6812
|
+
this.#wireLifecycle();
|
|
6813
|
+
this.#wireMessages();
|
|
6814
|
+
this.#wireGuilds();
|
|
6815
|
+
this.#wireGuildFeatures();
|
|
6816
|
+
this.#wireChannels();
|
|
6817
|
+
this.#wireMisc();
|
|
6818
|
+
}
|
|
6819
|
+
#createResourceContext() {
|
|
6820
|
+
return {
|
|
6590
6821
|
sendMessage: (channelId, options) => this.channels.send(channelId, options),
|
|
6591
6822
|
editMessage: (channelId, messageId, options) => this.channels.editMessage(channelId, messageId, options),
|
|
6592
6823
|
deleteMessage: (channelId, messageId, reason) => this.channels.deleteMessage(channelId, messageId, reason),
|
|
@@ -6600,7 +6831,7 @@ class Client extends EventEmitter2 {
|
|
|
6600
6831
|
pinMessage: (channelId, messageId, reason) => this.channels.pinMessage(channelId, messageId, reason),
|
|
6601
6832
|
unpinMessage: (channelId, messageId, reason) => this.channels.unpinMessage(channelId, messageId, reason),
|
|
6602
6833
|
collectInteractions: (options) => this.createCollector("interactionCreate" /* InteractionCreate */, options),
|
|
6603
|
-
memberPermissions: (guildId, memberId, roleIds, channelId) => this.#memberPermissions(guildId, memberId, roleIds, channelId),
|
|
6834
|
+
memberPermissions: (guildId, memberId, roleIds, channelId, timedOutUntil) => this.#memberPermissions(guildId, memberId, roleIds, channelId, timedOutUntil),
|
|
6604
6835
|
kickMember: (guildId, userId, reason) => this.guilds.members(guildId).kick(userId, reason),
|
|
6605
6836
|
banMember: (guildId, userId, options) => this.guilds.members(guildId).ban(userId, options),
|
|
6606
6837
|
editMember: (guildId, userId, options, reason) => this.guilds.members(guildId).edit(userId, options, reason),
|
|
@@ -6623,12 +6854,8 @@ class Client extends EventEmitter2 {
|
|
|
6623
6854
|
return this.channels.permissionOverwrites(channelId).update(targetId, bits, options);
|
|
6624
6855
|
}
|
|
6625
6856
|
};
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
token: options.token,
|
|
6629
|
-
intents: options.intents,
|
|
6630
|
-
...options.gateway
|
|
6631
|
-
});
|
|
6857
|
+
}
|
|
6858
|
+
#wireLifecycle() {
|
|
6632
6859
|
this.#gateway.on("READY", (data) => {
|
|
6633
6860
|
const ready = data;
|
|
6634
6861
|
this.user = ready.user;
|
|
@@ -6654,6 +6881,8 @@ class Client extends EventEmitter2 {
|
|
|
6654
6881
|
this.state = "idle";
|
|
6655
6882
|
this.emit("close" /* Close */, data);
|
|
6656
6883
|
});
|
|
6884
|
+
}
|
|
6885
|
+
#wireMessages() {
|
|
6657
6886
|
this.#gateway.on("MESSAGE_CREATE", (data) => {
|
|
6658
6887
|
const payload = data;
|
|
6659
6888
|
const message = new Message(payload, this.#resourceContext);
|
|
@@ -6701,6 +6930,8 @@ class Client extends EventEmitter2 {
|
|
|
6701
6930
|
this.#gateway.on("MESSAGE_REACTION_REMOVE_EMOJI", (data) => this.emit("messageReactionRemoveEmoji" /* MessageReactionRemoveEmoji */, data));
|
|
6702
6931
|
this.#gateway.on("MESSAGE_POLL_VOTE_ADD", (data) => this.emit("messagePollVoteAdd" /* MessagePollVoteAdd */, data));
|
|
6703
6932
|
this.#gateway.on("MESSAGE_POLL_VOTE_REMOVE", (data) => this.emit("messagePollVoteRemove" /* MessagePollVoteRemove */, data));
|
|
6933
|
+
}
|
|
6934
|
+
#wireGuilds() {
|
|
6704
6935
|
this.#gateway.on("GUILD_CREATE", (data) => {
|
|
6705
6936
|
const payload = data;
|
|
6706
6937
|
if (payload.unavailable) {
|
|
@@ -6801,6 +7032,8 @@ class Client extends EventEmitter2 {
|
|
|
6801
7032
|
roles.delete(event.role_id);
|
|
6802
7033
|
this.emit("guildRoleDelete" /* GuildRoleDelete */, event, removed);
|
|
6803
7034
|
});
|
|
7035
|
+
}
|
|
7036
|
+
#wireGuildFeatures() {
|
|
6804
7037
|
this.#gateway.on("GUILD_EMOJIS_UPDATE", (data) => {
|
|
6805
7038
|
const event = data;
|
|
6806
7039
|
let previous = null;
|
|
@@ -6897,6 +7130,8 @@ class Client extends EventEmitter2 {
|
|
|
6897
7130
|
this.emit("autoModerationRuleDelete" /* AutoModerationRuleDelete */, rule);
|
|
6898
7131
|
});
|
|
6899
7132
|
this.#gateway.on("AUTO_MODERATION_ACTION_EXECUTION", (data) => this.emit("autoModerationActionExecution" /* AutoModerationActionExecution */, data));
|
|
7133
|
+
}
|
|
7134
|
+
#wireChannels() {
|
|
6900
7135
|
this.#gateway.on("CHANNEL_CREATE", (data) => {
|
|
6901
7136
|
const channel = this.channels.upsert(data);
|
|
6902
7137
|
this.emit("channelCreate" /* ChannelCreate */, channel);
|
|
@@ -6964,6 +7199,8 @@ class Client extends EventEmitter2 {
|
|
|
6964
7199
|
this.emit("inviteDelete" /* InviteDelete */, invite);
|
|
6965
7200
|
});
|
|
6966
7201
|
this.#gateway.on("WEBHOOKS_UPDATE", (data) => this.emit("webhooksUpdate" /* WebhooksUpdate */, data));
|
|
7202
|
+
}
|
|
7203
|
+
#wireMisc() {
|
|
6967
7204
|
this.#gateway.on("VOICE_STATE_UPDATE", (data) => {
|
|
6968
7205
|
const state = data;
|
|
6969
7206
|
if (state.guild_id)
|
|
@@ -7039,7 +7276,7 @@ class Client extends EventEmitter2 {
|
|
|
7039
7276
|
get resourceContext() {
|
|
7040
7277
|
return this.#resourceContext;
|
|
7041
7278
|
}
|
|
7042
|
-
#memberPermissions(guildId, memberId, roleIds, channelId) {
|
|
7279
|
+
#memberPermissions(guildId, memberId, roleIds, channelId, timedOutUntil) {
|
|
7043
7280
|
const guild = this.guilds.get(guildId);
|
|
7044
7281
|
if (!guild)
|
|
7045
7282
|
return null;
|
|
@@ -7056,7 +7293,8 @@ class Client extends EventEmitter2 {
|
|
|
7056
7293
|
memberId,
|
|
7057
7294
|
memberRoleIds: [...roleIds],
|
|
7058
7295
|
roles: this.guilds.roles(guildId).values(),
|
|
7059
|
-
overwrites: channel?.permissionOverwrites
|
|
7296
|
+
overwrites: channel?.permissionOverwrites,
|
|
7297
|
+
timedOutUntil
|
|
7060
7298
|
});
|
|
7061
7299
|
}
|
|
7062
7300
|
permissionsFor(memberId, guildOrChannelId) {
|
|
@@ -7077,7 +7315,8 @@ class Client extends EventEmitter2 {
|
|
|
7077
7315
|
memberId,
|
|
7078
7316
|
memberRoleIds: member.roleIds,
|
|
7079
7317
|
roles: this.guilds.roles(guildId).values(),
|
|
7080
|
-
overwrites: channel?.permissionOverwrites
|
|
7318
|
+
overwrites: channel?.permissionOverwrites,
|
|
7319
|
+
timedOutUntil: member.timedOutUntil
|
|
7081
7320
|
});
|
|
7082
7321
|
}
|
|
7083
7322
|
fetchDefaultSoundboardSounds() {
|
|
@@ -7125,10 +7364,10 @@ class Client extends EventEmitter2 {
|
|
|
7125
7364
|
return Promise.reject(new Error("Client is unauthenticated."));
|
|
7126
7365
|
return this.rest.delete(Routes.interactionOriginalResponse(this.user.id, token));
|
|
7127
7366
|
}
|
|
7128
|
-
followUpInteraction(token, data) {
|
|
7367
|
+
async followUpInteraction(token, data) {
|
|
7129
7368
|
if (!this.user)
|
|
7130
7369
|
return Promise.reject(new Error("Client is unauthenticated."));
|
|
7131
|
-
return this.rest.post(
|
|
7370
|
+
return this.rest.post(Routes.webhook(this.user.id, token), toRequest(data, this.options.allowedMentions));
|
|
7132
7371
|
}
|
|
7133
7372
|
interactionWebhookMessage(method, applicationId, token, messageId, data) {
|
|
7134
7373
|
const path = messageId === "@original" ? Routes.interactionOriginalResponse(applicationId, token) : Routes.webhookMessage(applicationId, token, messageId);
|
|
@@ -7138,11 +7377,11 @@ class Client extends EventEmitter2 {
|
|
|
7138
7377
|
return this.rest.patch(path, data ? toRequest(data, this.options.allowedMentions) : data);
|
|
7139
7378
|
return this.rest.delete(path);
|
|
7140
7379
|
}
|
|
7141
|
-
fetchWebhook(id, token) {
|
|
7142
|
-
return this.rest.get(
|
|
7380
|
+
async fetchWebhook(id, token) {
|
|
7381
|
+
return this.rest.get(Routes.webhook(id, token));
|
|
7143
7382
|
}
|
|
7144
|
-
fetchGuildPreview(guildId) {
|
|
7145
|
-
return this.rest.get(
|
|
7383
|
+
async fetchGuildPreview(guildId) {
|
|
7384
|
+
return this.rest.get(Routes.guildPreview(guildId));
|
|
7146
7385
|
}
|
|
7147
7386
|
fetchVoiceRegions() {
|
|
7148
7387
|
return this.rest.get("/voice/regions");
|
|
@@ -7156,8 +7395,8 @@ class Client extends EventEmitter2 {
|
|
|
7156
7395
|
const qs = query.toString();
|
|
7157
7396
|
return this.rest.get(`/invites/${encodeURIComponent(code)}${qs ? `?${qs}` : ""}`);
|
|
7158
7397
|
}
|
|
7159
|
-
fetchSticker(id) {
|
|
7160
|
-
return this.rest.get(
|
|
7398
|
+
async fetchSticker(id) {
|
|
7399
|
+
return this.rest.get(Routes.sticker(id));
|
|
7161
7400
|
}
|
|
7162
7401
|
fetchPremiumStickerPacks() {
|
|
7163
7402
|
return this.rest.get(`/sticker-packs`);
|
|
@@ -7217,13 +7456,17 @@ function inlineCode(text) {
|
|
|
7217
7456
|
return `\`${text}\``;
|
|
7218
7457
|
}
|
|
7219
7458
|
function codeBlock(text, language = "") {
|
|
7220
|
-
|
|
7221
|
-
|
|
7459
|
+
const safe = text.replace(/```/g, "`\u200B``");
|
|
7460
|
+
const lang = language.replace(/[^\w+#.-]/g, "");
|
|
7461
|
+
return `\`\`\`${lang}
|
|
7462
|
+
${safe}
|
|
7222
7463
|
\`\`\``;
|
|
7223
7464
|
}
|
|
7224
7465
|
function link(label, url, title) {
|
|
7225
|
-
const
|
|
7226
|
-
|
|
7466
|
+
const text = label.replace(/[[\]\\]/g, "\\$&").replace(/\n/g, " ");
|
|
7467
|
+
const target = url.replace(/[()\s"]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`);
|
|
7468
|
+
const titlePart = title ? ` "${title.replace(/["\n]/g, "")}"` : "";
|
|
7469
|
+
return `[${text}](${target}${titlePart})`;
|
|
7227
7470
|
}
|
|
7228
7471
|
function blockQuote(text) {
|
|
7229
7472
|
return text.split(`
|
|
@@ -7262,14 +7505,9 @@ function validateSnowflake(id, field) {
|
|
|
7262
7505
|
}
|
|
7263
7506
|
// packages/handlers/src/index.ts
|
|
7264
7507
|
class HandlerRegistry {
|
|
7265
|
-
#handlers =
|
|
7508
|
+
#handlers = {};
|
|
7266
7509
|
on(event, handler) {
|
|
7267
|
-
|
|
7268
|
-
if (!handlers) {
|
|
7269
|
-
handlers = new Set;
|
|
7270
|
-
this.#handlers.set(event, handlers);
|
|
7271
|
-
}
|
|
7272
|
-
handlers.add(handler);
|
|
7510
|
+
(this.#handlers[event] ??= new Set).add(handler);
|
|
7273
7511
|
return this;
|
|
7274
7512
|
}
|
|
7275
7513
|
once(event, handler) {
|
|
@@ -7280,11 +7518,11 @@ class HandlerRegistry {
|
|
|
7280
7518
|
return this.on(event, wrapped);
|
|
7281
7519
|
}
|
|
7282
7520
|
off(event, handler) {
|
|
7283
|
-
this.#handlers
|
|
7521
|
+
this.#handlers[event]?.delete(handler);
|
|
7284
7522
|
return this;
|
|
7285
7523
|
}
|
|
7286
7524
|
async dispatch(event, ...args) {
|
|
7287
|
-
for (const handler of this.#handlers
|
|
7525
|
+
for (const handler of this.#handlers[event] ?? [])
|
|
7288
7526
|
await handler(...args);
|
|
7289
7527
|
}
|
|
7290
7528
|
emit(event, ...args) {
|
|
@@ -7294,7 +7532,7 @@ class HandlerRegistry {
|
|
|
7294
7532
|
// packages/sharding/package.json
|
|
7295
7533
|
var package_default2 = {
|
|
7296
7534
|
name: "@lunibee/sharding",
|
|
7297
|
-
version: "0.2.
|
|
7535
|
+
version: "0.2.4",
|
|
7298
7536
|
type: "module",
|
|
7299
7537
|
module: "./src/index.ts",
|
|
7300
7538
|
types: "./src/index.ts",
|
|
@@ -8039,6 +8277,9 @@ var SpeakingFlags = {
|
|
|
8039
8277
|
Soundshare: 2,
|
|
8040
8278
|
Priority: 4
|
|
8041
8279
|
};
|
|
8280
|
+
function listenerSet(sets, event) {
|
|
8281
|
+
return sets[event] ??= new Set;
|
|
8282
|
+
}
|
|
8042
8283
|
|
|
8043
8284
|
class VoiceConnection {
|
|
8044
8285
|
state = "disconnected" /* Disconnected */;
|
|
@@ -8048,7 +8289,7 @@ class VoiceConnection {
|
|
|
8048
8289
|
selfDeaf;
|
|
8049
8290
|
gateway;
|
|
8050
8291
|
udp;
|
|
8051
|
-
#listeners =
|
|
8292
|
+
#listeners = {};
|
|
8052
8293
|
receiver;
|
|
8053
8294
|
constructor(options) {
|
|
8054
8295
|
const resolved = typeof options === "string" ? { guildId: options } : options;
|
|
@@ -8064,14 +8305,11 @@ class VoiceConnection {
|
|
|
8064
8305
|
on(event, listener) {
|
|
8065
8306
|
if (typeof listener !== "function")
|
|
8066
8307
|
throw new TypeError("Voice listener must be a function.");
|
|
8067
|
-
|
|
8068
|
-
if (!listeners)
|
|
8069
|
-
this.#listeners.set(event, listeners = new Set);
|
|
8070
|
-
listeners.add(listener);
|
|
8308
|
+
listenerSet(this.#listeners, event).add(listener);
|
|
8071
8309
|
return this;
|
|
8072
8310
|
}
|
|
8073
8311
|
off(event, listener) {
|
|
8074
|
-
this.#listeners
|
|
8312
|
+
this.#listeners[event]?.delete(listener);
|
|
8075
8313
|
return this;
|
|
8076
8314
|
}
|
|
8077
8315
|
attachTransports(gateway, udp) {
|
|
@@ -8114,7 +8352,7 @@ class VoiceConnection {
|
|
|
8114
8352
|
this.receiver.close();
|
|
8115
8353
|
this.channelId = undefined;
|
|
8116
8354
|
this.#transition("destroyed" /* Destroyed */);
|
|
8117
|
-
this.#listeners
|
|
8355
|
+
this.#listeners = {};
|
|
8118
8356
|
}
|
|
8119
8357
|
setChannel(channelId) {
|
|
8120
8358
|
this.assertUsable();
|
|
@@ -8165,7 +8403,7 @@ class VoiceConnection {
|
|
|
8165
8403
|
this.state = next;
|
|
8166
8404
|
if (previous === next)
|
|
8167
8405
|
return;
|
|
8168
|
-
for (const listener of this.#listeners.
|
|
8406
|
+
for (const listener of this.#listeners.stateChange ?? []) {
|
|
8169
8407
|
try {
|
|
8170
8408
|
listener(next, previous);
|
|
8171
8409
|
} catch (error) {
|
|
@@ -8178,7 +8416,7 @@ class VoiceConnection {
|
|
|
8178
8416
|
}
|
|
8179
8417
|
}
|
|
8180
8418
|
#emit(event, ...args) {
|
|
8181
|
-
for (const listener of this.#listeners
|
|
8419
|
+
for (const listener of this.#listeners[event] ?? []) {
|
|
8182
8420
|
try {
|
|
8183
8421
|
listener(...args);
|
|
8184
8422
|
} catch {}
|
|
@@ -8205,7 +8443,7 @@ class AudioPlayer {
|
|
|
8205
8443
|
#stream;
|
|
8206
8444
|
#reader;
|
|
8207
8445
|
#resumeSignal;
|
|
8208
|
-
#
|
|
8446
|
+
#playerListeners = {};
|
|
8209
8447
|
get state() {
|
|
8210
8448
|
return this.#state;
|
|
8211
8449
|
}
|
|
@@ -8250,15 +8488,11 @@ class AudioPlayer {
|
|
|
8250
8488
|
}
|
|
8251
8489
|
}
|
|
8252
8490
|
on(event, listener) {
|
|
8253
|
-
|
|
8254
|
-
if (!set) {
|
|
8255
|
-
this.#listeners.set(event, set = new Set);
|
|
8256
|
-
}
|
|
8257
|
-
set.add(listener);
|
|
8491
|
+
listenerSet(this.#playerListeners, event).add(listener);
|
|
8258
8492
|
return this;
|
|
8259
8493
|
}
|
|
8260
8494
|
off(event, listener) {
|
|
8261
|
-
this.#
|
|
8495
|
+
this.#playerListeners[event]?.delete(listener);
|
|
8262
8496
|
return this;
|
|
8263
8497
|
}
|
|
8264
8498
|
onChunk(chunk) {}
|
|
@@ -8300,7 +8534,7 @@ class AudioPlayer {
|
|
|
8300
8534
|
this.#emit("error", err instanceof Error ? err : new VoiceError(String(err)));
|
|
8301
8535
|
}
|
|
8302
8536
|
#emit(event, ...args) {
|
|
8303
|
-
for (const listener of this.#
|
|
8537
|
+
for (const listener of this.#playerListeners[event] ?? []) {
|
|
8304
8538
|
try {
|
|
8305
8539
|
listener(...args);
|
|
8306
8540
|
} catch {}
|
|
@@ -8562,24 +8796,6 @@ function url(value, field) {
|
|
|
8562
8796
|
}
|
|
8563
8797
|
var EmbedBuilder = CreateEmbed;
|
|
8564
8798
|
// packages/builders/src/components.ts
|
|
8565
|
-
var ComponentEnum = {
|
|
8566
|
-
ActionRow: 1,
|
|
8567
|
-
Button: 2,
|
|
8568
|
-
StringSelect: 3,
|
|
8569
|
-
TextInput: 4,
|
|
8570
|
-
UserSelect: 5,
|
|
8571
|
-
RoleSelect: 6,
|
|
8572
|
-
MentionableSelect: 7,
|
|
8573
|
-
ChannelSelect: 8,
|
|
8574
|
-
Section: 9,
|
|
8575
|
-
TextDisplay: 10,
|
|
8576
|
-
Thumbnail: 11,
|
|
8577
|
-
MediaGallery: 12,
|
|
8578
|
-
File: 13,
|
|
8579
|
-
Separator: 14,
|
|
8580
|
-
ContentInventoryEntry: 16,
|
|
8581
|
-
Container: 17
|
|
8582
|
-
};
|
|
8583
8799
|
var TextInputType = { Short: 1, Paragraph: 2 };
|
|
8584
8800
|
|
|
8585
8801
|
class CreateActionRow {
|
|
@@ -8607,38 +8823,50 @@ class CreateActionRow {
|
|
|
8607
8823
|
}
|
|
8608
8824
|
}
|
|
8609
8825
|
|
|
8610
|
-
class
|
|
8611
|
-
#
|
|
8612
|
-
|
|
8613
|
-
|
|
8826
|
+
class CreateSelectMenu {
|
|
8827
|
+
#select;
|
|
8828
|
+
constructor(data) {
|
|
8829
|
+
this.#select = data;
|
|
8830
|
+
}
|
|
8614
8831
|
setCustomId(value) {
|
|
8615
8832
|
validateText(value, 100, "Component custom ID");
|
|
8616
|
-
this.#
|
|
8833
|
+
this.#select.custom_id = value;
|
|
8617
8834
|
return this;
|
|
8618
8835
|
}
|
|
8619
8836
|
setPlaceholder(value) {
|
|
8620
8837
|
validateText(value, 150, "Component placeholder");
|
|
8621
|
-
this.#
|
|
8838
|
+
this.#select.placeholder = value;
|
|
8622
8839
|
return this;
|
|
8623
8840
|
}
|
|
8624
8841
|
setMinValues(value) {
|
|
8625
8842
|
validateCount(value, "min_values", 0);
|
|
8626
|
-
this.#
|
|
8843
|
+
this.#select.min_values = value;
|
|
8627
8844
|
return this;
|
|
8628
8845
|
}
|
|
8629
8846
|
setMaxValues(value) {
|
|
8630
8847
|
validateCount(value, "max_values", 1);
|
|
8631
|
-
this.#
|
|
8848
|
+
this.#select.max_values = value;
|
|
8632
8849
|
return this;
|
|
8633
8850
|
}
|
|
8634
8851
|
setRequired(value = true) {
|
|
8635
|
-
this.#
|
|
8852
|
+
this.#select.required = value;
|
|
8636
8853
|
return this;
|
|
8637
8854
|
}
|
|
8638
8855
|
setDisabled(value = true) {
|
|
8639
|
-
this.#
|
|
8856
|
+
this.#select.disabled = value;
|
|
8640
8857
|
return this;
|
|
8641
8858
|
}
|
|
8859
|
+
}
|
|
8860
|
+
|
|
8861
|
+
class CreateStringSelect extends CreateSelectMenu {
|
|
8862
|
+
#data;
|
|
8863
|
+
constructor() {
|
|
8864
|
+
const data = {
|
|
8865
|
+
type: ComponentEnum.StringSelect
|
|
8866
|
+
};
|
|
8867
|
+
super(data);
|
|
8868
|
+
this.#data = data;
|
|
8869
|
+
}
|
|
8642
8870
|
addOptions(...options) {
|
|
8643
8871
|
if (!options.length)
|
|
8644
8872
|
throw new TypeError("At least one select option is required.");
|
|
@@ -8754,40 +8982,14 @@ class CreateButton {
|
|
|
8754
8982
|
}
|
|
8755
8983
|
}
|
|
8756
8984
|
|
|
8757
|
-
class CreateEntitySelect {
|
|
8985
|
+
class CreateEntitySelect extends CreateSelectMenu {
|
|
8758
8986
|
#data;
|
|
8759
8987
|
constructor(type) {
|
|
8760
8988
|
if (type !== ComponentEnum.UserSelect && type !== ComponentEnum.RoleSelect && type !== ComponentEnum.MentionableSelect && type !== ComponentEnum.ChannelSelect)
|
|
8761
8989
|
throw new TypeError("Invalid select component type.");
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
validateText(value, 100, "Component custom ID");
|
|
8766
|
-
this.#data.custom_id = value;
|
|
8767
|
-
return this;
|
|
8768
|
-
}
|
|
8769
|
-
setPlaceholder(value) {
|
|
8770
|
-
validateText(value, 150, "Component placeholder");
|
|
8771
|
-
this.#data.placeholder = value;
|
|
8772
|
-
return this;
|
|
8773
|
-
}
|
|
8774
|
-
setMinValues(value) {
|
|
8775
|
-
validateCount(value, "min_values", 0);
|
|
8776
|
-
this.#data.min_values = value;
|
|
8777
|
-
return this;
|
|
8778
|
-
}
|
|
8779
|
-
setMaxValues(value) {
|
|
8780
|
-
validateCount(value, "max_values", 1);
|
|
8781
|
-
this.#data.max_values = value;
|
|
8782
|
-
return this;
|
|
8783
|
-
}
|
|
8784
|
-
setRequired(value = true) {
|
|
8785
|
-
this.#data.required = value;
|
|
8786
|
-
return this;
|
|
8787
|
-
}
|
|
8788
|
-
setDisabled(value = true) {
|
|
8789
|
-
this.#data.disabled = value;
|
|
8790
|
-
return this;
|
|
8990
|
+
const data = { type };
|
|
8991
|
+
super(data);
|
|
8992
|
+
this.#data = data;
|
|
8791
8993
|
}
|
|
8792
8994
|
setDefaultValues(...values) {
|
|
8793
8995
|
this.#data.default_values = values.map((value) => ({ ...value }));
|
|
@@ -9245,16 +9447,7 @@ class CreateSlashCommand {
|
|
|
9245
9447
|
return structuredClone(this.#data);
|
|
9246
9448
|
}
|
|
9247
9449
|
addOption(option) {
|
|
9248
|
-
|
|
9249
|
-
if (options.length >= 25)
|
|
9250
|
-
throw new RangeError("An application command cannot contain more than 25 options.");
|
|
9251
|
-
const payload = option.toJSON();
|
|
9252
|
-
if (options.some((existing) => existing.name === payload.name))
|
|
9253
|
-
throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
|
|
9254
|
-
if (payload.required === true && options.some((existing) => existing.required !== true))
|
|
9255
|
-
throw new RangeError("Required application command options must be placed before optional options.");
|
|
9256
|
-
options.push(payload);
|
|
9257
|
-
this.#data.options = options;
|
|
9450
|
+
this.#data.options = appendOption(this.#data.options, option.toJSON(), "application command");
|
|
9258
9451
|
return this;
|
|
9259
9452
|
}
|
|
9260
9453
|
}
|
|
@@ -9292,21 +9485,9 @@ class CreateStringOption extends CreateCommandOption {
|
|
|
9292
9485
|
super(ApplicationCommandOptionEnum2.String);
|
|
9293
9486
|
}
|
|
9294
9487
|
addChoices(...choices) {
|
|
9295
|
-
const
|
|
9296
|
-
if (!choices.length)
|
|
9297
|
-
throw new TypeError("At least one choice is required.");
|
|
9298
|
-
if (this.data.autocomplete === true)
|
|
9299
|
-
throw new RangeError("Autocomplete options cannot define choices.");
|
|
9300
|
-
if (current.length + choices.length > 25)
|
|
9301
|
-
throw new RangeError("An option cannot contain more than 25 choices.");
|
|
9302
|
-
for (const choice of choices) {
|
|
9303
|
-
validateText2(choice.name, "Choice name", 100);
|
|
9488
|
+
for (const choice of choices)
|
|
9304
9489
|
validateText2(choice.value, "Choice value", 100);
|
|
9305
|
-
|
|
9306
|
-
this.data.choices = [
|
|
9307
|
-
...current,
|
|
9308
|
-
...choices.map((choice) => ({ ...choice }))
|
|
9309
|
-
];
|
|
9490
|
+
appendChoices(this.data, choices);
|
|
9310
9491
|
return this;
|
|
9311
9492
|
}
|
|
9312
9493
|
setMinLength(value) {
|
|
@@ -9323,18 +9504,21 @@ class CreateStringOption extends CreateCommandOption {
|
|
|
9323
9504
|
}
|
|
9324
9505
|
}
|
|
9325
9506
|
|
|
9326
|
-
class
|
|
9327
|
-
|
|
9328
|
-
|
|
9507
|
+
class CreateNumericOption extends CreateCommandOption {
|
|
9508
|
+
#integer;
|
|
9509
|
+
constructor(type, integer) {
|
|
9510
|
+
super(type);
|
|
9511
|
+
this.#integer = integer;
|
|
9329
9512
|
}
|
|
9330
9513
|
setMinValue(value) {
|
|
9331
|
-
validateNumberRange(value, -
|
|
9514
|
+
validateNumberRange(value, -MAX_SAFE, MAX_SAFE, "min_value", this.#integer);
|
|
9332
9515
|
this.data.min_value = value;
|
|
9333
9516
|
return this;
|
|
9334
9517
|
}
|
|
9335
9518
|
setMaxValue(value) {
|
|
9336
|
-
validateNumberRange(value, -
|
|
9337
|
-
|
|
9519
|
+
validateNumberRange(value, -MAX_SAFE, MAX_SAFE, "max_value", this.#integer);
|
|
9520
|
+
const min = this.data.min_value;
|
|
9521
|
+
if (min !== undefined && min > value)
|
|
9338
9522
|
throw new RangeError("min_value cannot exceed max_value.");
|
|
9339
9523
|
this.data.max_value = value;
|
|
9340
9524
|
return this;
|
|
@@ -9346,50 +9530,20 @@ class CreateIntegerOption extends CreateCommandOption {
|
|
|
9346
9530
|
return this;
|
|
9347
9531
|
}
|
|
9348
9532
|
addChoices(...choices) {
|
|
9349
|
-
|
|
9350
|
-
if (!choices.length)
|
|
9351
|
-
throw new TypeError("At least one choice is required.");
|
|
9352
|
-
if (this.data.autocomplete === true)
|
|
9353
|
-
throw new RangeError("Autocomplete options cannot define choices.");
|
|
9354
|
-
if (current.length + choices.length > 25)
|
|
9355
|
-
throw new RangeError("An option cannot contain more than 25 choices.");
|
|
9356
|
-
this.data.choices = [...current, ...choices];
|
|
9533
|
+
appendChoices(this.data, choices);
|
|
9357
9534
|
return this;
|
|
9358
9535
|
}
|
|
9359
9536
|
}
|
|
9360
9537
|
|
|
9361
|
-
class
|
|
9538
|
+
class CreateIntegerOption extends CreateNumericOption {
|
|
9362
9539
|
constructor() {
|
|
9363
|
-
super(ApplicationCommandOptionEnum2.
|
|
9540
|
+
super(ApplicationCommandOptionEnum2.Integer, true);
|
|
9364
9541
|
}
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
setMaxValue(value) {
|
|
9371
|
-
validateNumberRange(value, -9007199254740991, 9007199254740991, "max_value", false);
|
|
9372
|
-
if (this.data.min_value !== undefined && this.data.min_value > value)
|
|
9373
|
-
throw new RangeError("min_value cannot exceed max_value.");
|
|
9374
|
-
this.data.max_value = value;
|
|
9375
|
-
return this;
|
|
9376
|
-
}
|
|
9377
|
-
setAutocomplete(enabled = true) {
|
|
9378
|
-
if (enabled && Array.isArray(this.data.choices) && this.data.choices.length)
|
|
9379
|
-
throw new RangeError("Autocomplete options cannot define choices.");
|
|
9380
|
-
this.data.autocomplete = enabled;
|
|
9381
|
-
return this;
|
|
9382
|
-
}
|
|
9383
|
-
addChoices(...choices) {
|
|
9384
|
-
const current = this.data.choices ?? [];
|
|
9385
|
-
if (!choices.length)
|
|
9386
|
-
throw new TypeError("At least one choice is required.");
|
|
9387
|
-
if (this.data.autocomplete === true)
|
|
9388
|
-
throw new RangeError("Autocomplete options cannot define choices.");
|
|
9389
|
-
if (current.length + choices.length > 25)
|
|
9390
|
-
throw new RangeError("An option cannot contain more than 25 choices.");
|
|
9391
|
-
this.data.choices = [...current, ...choices];
|
|
9392
|
-
return this;
|
|
9542
|
+
}
|
|
9543
|
+
|
|
9544
|
+
class CreateNumberOption extends CreateNumericOption {
|
|
9545
|
+
constructor() {
|
|
9546
|
+
super(ApplicationCommandOptionEnum2.Number, false);
|
|
9393
9547
|
}
|
|
9394
9548
|
}
|
|
9395
9549
|
|
|
@@ -9468,17 +9622,9 @@ class CreateSubcommand extends CreateCommandOption {
|
|
|
9468
9622
|
}
|
|
9469
9623
|
addChildOption(option) {
|
|
9470
9624
|
const options = this.data.options ?? [];
|
|
9471
|
-
if (options.length >= 25)
|
|
9472
|
-
throw new RangeError("A subcommand cannot contain more than 25 options.");
|
|
9473
|
-
const payload = option.toJSON();
|
|
9474
|
-
if (options.some((existing) => existing.name === payload.name))
|
|
9475
|
-
throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
|
|
9476
|
-
if (payload.required === true && options.some((existing) => existing.required !== true))
|
|
9477
|
-
throw new RangeError("Required subcommand options must be placed before optional options.");
|
|
9478
9625
|
if (options.some((existing) => existing.type === ApplicationCommandOptionEnum2.Subcommand))
|
|
9479
9626
|
throw new RangeError("Subcommands cannot contain nested subcommands.");
|
|
9480
|
-
options.
|
|
9481
|
-
this.data.options = options;
|
|
9627
|
+
this.data.options = appendOption(options, option.toJSON(), "subcommand");
|
|
9482
9628
|
return this;
|
|
9483
9629
|
}
|
|
9484
9630
|
}
|
|
@@ -9501,6 +9647,29 @@ class CreateSubcommandGroup extends CreateCommandOption {
|
|
|
9501
9647
|
return this;
|
|
9502
9648
|
}
|
|
9503
9649
|
}
|
|
9650
|
+
var MAX_SAFE = Number.MAX_SAFE_INTEGER;
|
|
9651
|
+
function appendOption(options, payload, parent) {
|
|
9652
|
+
const list = options ?? [];
|
|
9653
|
+
if (list.length >= 25)
|
|
9654
|
+
throw new RangeError(`${parent === "subcommand" ? "A subcommand" : "An application command"} cannot contain more than 25 options.`);
|
|
9655
|
+
if (list.some((existing) => existing.name === payload.name))
|
|
9656
|
+
throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
|
|
9657
|
+
if (payload.required === true && list.some((existing) => existing.required !== true))
|
|
9658
|
+
throw new RangeError(`Required ${parent} options must be placed before optional options.`);
|
|
9659
|
+
return [...list, payload];
|
|
9660
|
+
}
|
|
9661
|
+
function appendChoices(data, choices) {
|
|
9662
|
+
const current = data.choices ?? [];
|
|
9663
|
+
if (!choices.length)
|
|
9664
|
+
throw new TypeError("At least one choice is required.");
|
|
9665
|
+
if (data.autocomplete === true)
|
|
9666
|
+
throw new RangeError("Autocomplete options cannot define choices.");
|
|
9667
|
+
if (current.length + choices.length > 25)
|
|
9668
|
+
throw new RangeError("An option cannot contain more than 25 choices.");
|
|
9669
|
+
for (const choice of choices)
|
|
9670
|
+
validateText2(choice.name, "Choice name", 100);
|
|
9671
|
+
data.choices = [...current, ...choices.map((choice) => ({ ...choice }))];
|
|
9672
|
+
}
|
|
9504
9673
|
function validateName(value, field) {
|
|
9505
9674
|
if (!/^[\p{L}\p{N}_-]{1,32}$/u.test(value) || value !== value.toLowerCase())
|
|
9506
9675
|
throw new RangeError(`${field} must contain 1-32 lowercase letters, numbers, underscores, or hyphens.`);
|
|
@@ -9589,13 +9758,14 @@ var SubcommandGroupBuilder = CreateSubcommandGroup;
|
|
|
9589
9758
|
var UserCommandBuilder = CreateUserCommand;
|
|
9590
9759
|
var UserOptionBuilder = CreateUserOption;
|
|
9591
9760
|
// packages/builders/src/attachment.ts
|
|
9592
|
-
import { readFile } from "fs/promises";
|
|
9593
|
-
import { basename } from "path";
|
|
9761
|
+
import { readFile, realpath } from "fs/promises";
|
|
9762
|
+
import { basename, isAbsolute, relative, resolve } from "path";
|
|
9594
9763
|
|
|
9595
9764
|
class CreateAttachment {
|
|
9596
9765
|
name;
|
|
9597
9766
|
description;
|
|
9598
9767
|
file;
|
|
9768
|
+
root;
|
|
9599
9769
|
constructor(file, data) {
|
|
9600
9770
|
this.file = file;
|
|
9601
9771
|
if (typeof data === "string") {
|
|
@@ -9603,6 +9773,7 @@ class CreateAttachment {
|
|
|
9603
9773
|
} else {
|
|
9604
9774
|
this.name = data?.name ?? (typeof file === "string" ? basename(file) : "file.bin");
|
|
9605
9775
|
this.description = data?.description;
|
|
9776
|
+
this.root = data?.root;
|
|
9606
9777
|
}
|
|
9607
9778
|
}
|
|
9608
9779
|
setName(name) {
|
|
@@ -9619,7 +9790,8 @@ class CreateAttachment {
|
|
|
9619
9790
|
}
|
|
9620
9791
|
async toBuffer() {
|
|
9621
9792
|
if (typeof this.file === "string") {
|
|
9622
|
-
const
|
|
9793
|
+
const path = this.root === undefined ? this.file : await insideRoot(this.root, this.file);
|
|
9794
|
+
const buffer = await readFile(path);
|
|
9623
9795
|
return new Uint8Array(buffer);
|
|
9624
9796
|
}
|
|
9625
9797
|
if (this.file instanceof Uint8Array)
|
|
@@ -9637,6 +9809,16 @@ class CreateAttachment {
|
|
|
9637
9809
|
}
|
|
9638
9810
|
}
|
|
9639
9811
|
var AttachmentBuilder = CreateAttachment;
|
|
9812
|
+
async function insideRoot(root, file) {
|
|
9813
|
+
const base = await realpath(root);
|
|
9814
|
+
const target = await realpath(resolve(base, file)).catch(() => {
|
|
9815
|
+
throw new Error("Attachment file was not found inside its root.");
|
|
9816
|
+
});
|
|
9817
|
+
const rel = relative(base, target);
|
|
9818
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute(rel))
|
|
9819
|
+
throw new Error("Attachment file is outside its root folder.");
|
|
9820
|
+
return target;
|
|
9821
|
+
}
|
|
9640
9822
|
export {
|
|
9641
9823
|
ActionRowBuilder,
|
|
9642
9824
|
ActivityEnum,
|
|
@@ -9910,4 +10092,4 @@ export {
|
|
|
9910
10092
|
userMention
|
|
9911
10093
|
};
|
|
9912
10094
|
|
|
9913
|
-
//# debugId=
|
|
10095
|
+
//# debugId=4ECD86428171907F64756E2164756E21
|