lunibee 0.3.0 → 0.3.2
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/dist/builders/attachment.d.ts +1 -0
- package/dist/builders/clone.d.ts +10 -0
- package/dist/builders/commands.d.ts +1 -1
- package/dist/builders/components.d.ts +24 -5
- package/dist/builders/embed.d.ts +1 -0
- package/dist/builders/index.js +68 -17
- package/dist/builders/index.js.map +10 -9
- package/dist/collection/index.d.ts +1 -0
- package/dist/collection/index.js +297 -19
- package/dist/collection/index.js.map +5 -4
- package/dist/collection/redis.d.ts +98 -0
- package/dist/core/collector.d.ts +8 -0
- package/dist/core/events.d.ts +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +6252 -4704
- package/dist/core/index.js.map +47 -40
- package/dist/core/permissions.d.ts +3 -402
- package/dist/core/redis-cache.d.ts +85 -0
- package/dist/formatters/index.d.ts +5 -1
- package/dist/formatters/index.js +7 -3
- package/dist/formatters/index.js.map +3 -3
- package/dist/handlers/index.js +11 -2
- package/dist/handlers/index.js.map +3 -3
- package/dist/index.js +10481 -6148
- package/dist/index.js.map +70 -56
- package/dist/managers/application.d.ts +10 -6
- package/dist/managers/base.d.ts +4 -1
- package/dist/managers/guild.d.ts +3 -1
- package/dist/managers/index.d.ts +6 -1
- package/dist/managers/index.js +365 -103
- package/dist/managers/index.js.map +19 -22
- package/dist/managers/member.d.ts +3 -1
- package/dist/managers/message.d.ts +13 -4
- package/dist/managers/thread.d.ts +3 -3
- package/dist/rest/decoder.d.ts +2 -0
- package/dist/rest/errors.d.ts +13 -2
- package/dist/rest/headers.d.ts +31 -0
- package/dist/rest/identity.d.ts +31 -0
- package/dist/rest/index.d.ts +99 -6
- package/dist/rest/index.js +1412 -231
- package/dist/rest/index.js.map +16 -13
- package/dist/rest/limiter.d.ts +75 -10
- package/dist/rest/redis.d.ts +103 -22
- package/dist/rest/scheduler.d.ts +13 -0
- package/dist/rest/store.d.ts +135 -12
- package/dist/rest/telemetry.d.ts +151 -0
- package/dist/rest/transport.d.ts +9 -0
- package/dist/rest/webhook.d.ts +18 -6
- package/dist/sharding/bus.d.ts +12 -2
- package/dist/sharding/cluster.d.ts +225 -15
- package/dist/sharding/context.d.ts +41 -0
- package/dist/sharding/gateway-bot.d.ts +20 -0
- package/dist/sharding/health.d.ts +94 -0
- package/dist/sharding/host.d.ts +76 -0
- package/dist/sharding/identify.d.ts +64 -0
- package/dist/sharding/index.d.ts +62 -12
- package/dist/sharding/index.js +2459 -202
- package/dist/sharding/index.js.map +21 -13
- package/dist/sharding/protocol.d.ts +47 -0
- package/dist/sharding/remote-protocol.d.ts +100 -0
- package/dist/sharding/remote.d.ts +134 -0
- package/dist/sharding/requests.d.ts +54 -0
- package/dist/sharding/supervisor.d.ts +1 -1
- package/dist/sharding/transport.d.ts +6 -5
- package/dist/sharding/worker.d.ts +55 -0
- package/dist/structures/base.d.ts +16 -5
- package/dist/structures/index.d.ts +1 -1
- package/dist/structures/index.js +57 -91
- package/dist/structures/index.js.map +10 -18
- package/dist/structures/options.d.ts +3 -2
- package/dist/structures/permissions.d.ts +409 -0
- package/dist/structures/resources.d.ts +4 -1
- package/dist/types/gateway.d.ts +7 -0
- package/dist/types/index.d.ts +14 -4
- package/dist/types/index.js.map +3 -3
- package/dist/utils/args.d.ts +3 -1
- package/dist/utils/index.d.ts +6 -1
- package/dist/utils/index.js +17 -10
- package/dist/utils/index.js.map +4 -4
- package/dist/voice/index.d.ts +7 -1
- package/dist/voice/index.js +33 -10
- package/dist/voice/index.js.map +3 -3
- package/dist/ws/index.d.ts +3 -1
- package/dist/ws/index.js +33 -5
- package/dist/ws/index.js.map +6 -6
- package/dist/ws/send-budget.d.ts +1 -1
- package/package.json +22 -17
package/dist/managers/index.js
CHANGED
|
@@ -1,4 +1,102 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// packages/collection/src/redis.ts
|
|
3
|
+
var PRELUDE = `
|
|
4
|
+
local exp, lru, clock, ep = KEYS[1], KEYS[2], KEYS[3], ARGV[1]
|
|
5
|
+
local t = redis.call('TIME')
|
|
6
|
+
local now = tonumber(t[1]) * 1000 + math.floor(tonumber(t[2]) / 1000)
|
|
7
|
+
local out = {}
|
|
8
|
+
local function drop(m, reason)
|
|
9
|
+
local v = redis.call('GET', ep .. m)
|
|
10
|
+
redis.call('DEL', ep .. m)
|
|
11
|
+
redis.call('ZREM', exp, m)
|
|
12
|
+
redis.call('ZREM', lru, m)
|
|
13
|
+
if reason then
|
|
14
|
+
table.insert(out, m)
|
|
15
|
+
table.insert(out, v or false)
|
|
16
|
+
table.insert(out, reason)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
local gone = redis.call('ZRANGEBYSCORE', exp, '-inf', now, 'LIMIT', 0, 1000)
|
|
20
|
+
for _, m in ipairs(gone) do drop(m, 'expired') end
|
|
21
|
+
local function touch(m) redis.call('ZADD', lru, redis.call('INCR', clock), m) end
|
|
22
|
+
`;
|
|
23
|
+
var SET_SCRIPT = `${PRELUDE}
|
|
24
|
+
local m, payload, ttl, max, mode = ARGV[2], ARGV[3], tonumber(ARGV[4]), tonumber(ARGV[5]), ARGV[6]
|
|
25
|
+
if mode == 'nx' then
|
|
26
|
+
local cur = redis.call('GET', ep .. m)
|
|
27
|
+
if cur then
|
|
28
|
+
touch(m)
|
|
29
|
+
table.insert(out, 1, cur)
|
|
30
|
+
return out
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
local env = ttl .. ':' .. payload
|
|
34
|
+
if ttl > 0 then
|
|
35
|
+
-- The key outlives its logical expiry by a grace second, so the prune
|
|
36
|
+
-- that reports the expiry can still hand the value to onEvict.
|
|
37
|
+
redis.call('SET', ep .. m, env, 'PX', ttl + 1000)
|
|
38
|
+
redis.call('ZADD', exp, now + ttl, m)
|
|
39
|
+
else
|
|
40
|
+
redis.call('SET', ep .. m, env)
|
|
41
|
+
redis.call('ZREM', exp, m)
|
|
42
|
+
end
|
|
43
|
+
touch(m)
|
|
44
|
+
if max > 0 then
|
|
45
|
+
local n = redis.call('ZCARD', lru)
|
|
46
|
+
while n > max do
|
|
47
|
+
local popped = redis.call('ZPOPMIN', lru)
|
|
48
|
+
local victim = popped[1]
|
|
49
|
+
if victim == nil then break end
|
|
50
|
+
if victim ~= m then drop(victim, 'evicted') end
|
|
51
|
+
n = n - 1
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
table.insert(out, 1, false)
|
|
55
|
+
return out
|
|
56
|
+
`;
|
|
57
|
+
var GET_SCRIPT = `${PRELUDE}
|
|
58
|
+
local m, slide, mark = ARGV[2], ARGV[3], ARGV[4]
|
|
59
|
+
local env = redis.call('GET', ep .. m)
|
|
60
|
+
if not env then
|
|
61
|
+
redis.call('ZREM', exp, m)
|
|
62
|
+
redis.call('ZREM', lru, m)
|
|
63
|
+
table.insert(out, 1, false)
|
|
64
|
+
return out
|
|
65
|
+
end
|
|
66
|
+
if mark == '1' then touch(m) end
|
|
67
|
+
if slide == '1' then
|
|
68
|
+
local ttl = tonumber(string.match(env, '^(%d+):'))
|
|
69
|
+
if ttl and ttl > 0 then
|
|
70
|
+
redis.call('PEXPIRE', ep .. m, ttl + 1000)
|
|
71
|
+
redis.call('ZADD', exp, now + ttl, m)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
table.insert(out, 1, env)
|
|
75
|
+
return out
|
|
76
|
+
`;
|
|
77
|
+
var DELETE_SCRIPT = `${PRELUDE}
|
|
78
|
+
local m = ARGV[2]
|
|
79
|
+
local existed = redis.call('EXISTS', ep .. m)
|
|
80
|
+
drop(m, nil)
|
|
81
|
+
table.insert(out, 1, existed)
|
|
82
|
+
return out
|
|
83
|
+
`;
|
|
84
|
+
var LIST_SCRIPT = `${PRELUDE}
|
|
85
|
+
local what = ARGV[2]
|
|
86
|
+
if what == 'clear' then
|
|
87
|
+
local n = 0
|
|
88
|
+
repeat
|
|
89
|
+
local batch = redis.call('ZRANGE', lru, 0, 999)
|
|
90
|
+
for _, m in ipairs(batch) do drop(m, nil) end
|
|
91
|
+
n = n + #batch
|
|
92
|
+
until #batch == 0
|
|
93
|
+
redis.call('DEL', exp, lru, clock)
|
|
94
|
+
return {n}
|
|
95
|
+
end
|
|
96
|
+
local result = what == 'size' and redis.call('ZCARD', lru) or redis.call('ZRANGE', lru, 0, -1)
|
|
97
|
+
return {result, unpack(out)}
|
|
98
|
+
`;
|
|
99
|
+
|
|
2
100
|
// packages/collection/src/index.ts
|
|
3
101
|
function newPolicy(options = {}) {
|
|
4
102
|
return {
|
|
@@ -56,21 +154,35 @@ class Collection extends Map {
|
|
|
56
154
|
this.set(key, value);
|
|
57
155
|
}
|
|
58
156
|
set(key, value, ttl) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
assertTTL(ttl);
|
|
62
|
-
let window = ttl ?? this.#policy?.ttl;
|
|
63
|
-
const jitter = this.#policy?.jitter ?? 0;
|
|
64
|
-
if (window !== undefined && jitter > 0)
|
|
65
|
-
window = Math.max(1, window * (1 - jitter * Math.random()));
|
|
66
|
-
if (window !== undefined)
|
|
67
|
-
this.#policy ??= newPolicy();
|
|
68
|
-
if (!this.#policy)
|
|
157
|
+
let policy = this.#policy;
|
|
158
|
+
if (ttl === undefined && policy === undefined)
|
|
69
159
|
return super.set(key, value);
|
|
70
|
-
|
|
160
|
+
if (ttl !== undefined)
|
|
161
|
+
assertTTL(ttl);
|
|
162
|
+
let window = ttl ?? policy?.ttl;
|
|
163
|
+
if (window !== undefined && policy !== undefined && policy.jitter > 0)
|
|
164
|
+
window = Math.max(1, window * (1 - policy.jitter * Math.random()));
|
|
165
|
+
if (policy === undefined) {
|
|
166
|
+
if (window === undefined)
|
|
167
|
+
return super.set(key, value);
|
|
168
|
+
policy = this.#policy = newPolicy();
|
|
169
|
+
}
|
|
170
|
+
const entry = policy.entries.get(key);
|
|
71
171
|
super.set(key, value);
|
|
72
|
-
|
|
73
|
-
|
|
172
|
+
if (entry !== undefined && window !== undefined && entry.window !== 0) {
|
|
173
|
+
const deadline = Date.now() + window;
|
|
174
|
+
if (deadline >= entry.filed) {
|
|
175
|
+
entry.value = value;
|
|
176
|
+
entry.deadline = deadline;
|
|
177
|
+
entry.window = window;
|
|
178
|
+
if (entry.inLru)
|
|
179
|
+
this.#promote(policy, entry);
|
|
180
|
+
return this;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
this.#track(key, value, window, entry);
|
|
184
|
+
if (policy.maxSize !== undefined && policy.lruSize > policy.maxSize)
|
|
185
|
+
this.#enforceCap();
|
|
74
186
|
return this;
|
|
75
187
|
}
|
|
76
188
|
setWithoutTTL(key, value) {
|
|
@@ -226,10 +338,10 @@ class Collection extends Map {
|
|
|
226
338
|
this.#unlink(policy, entry);
|
|
227
339
|
policy.entries.delete(key);
|
|
228
340
|
}
|
|
229
|
-
#track(key, value, window,
|
|
341
|
+
#track(key, value, window, existing) {
|
|
230
342
|
const policy = this.#policy;
|
|
231
343
|
const lru = policy.maxSize !== undefined;
|
|
232
|
-
let entry =
|
|
344
|
+
let entry = existing;
|
|
233
345
|
if (entry)
|
|
234
346
|
entry.value = value;
|
|
235
347
|
if (window === undefined) {
|
|
@@ -361,11 +473,20 @@ class Collection extends Map {
|
|
|
361
473
|
while (policy.lruSize > max) {
|
|
362
474
|
const oldest = policy.oldest;
|
|
363
475
|
const value = policy.onEvict ? super.get(oldest.key) : undefined;
|
|
364
|
-
|
|
476
|
+
const next = oldest.newer;
|
|
477
|
+
policy.oldest = next;
|
|
478
|
+
if (next)
|
|
479
|
+
next.older = undefined;
|
|
480
|
+
else
|
|
481
|
+
policy.newest = undefined;
|
|
482
|
+
oldest.newer = undefined;
|
|
483
|
+
oldest.inLru = false;
|
|
484
|
+
policy.lruSize--;
|
|
365
485
|
policy.entries.delete(oldest.key);
|
|
366
486
|
super.delete(oldest.key);
|
|
367
487
|
policy.evicted++;
|
|
368
|
-
|
|
488
|
+
if (policy.onEvict)
|
|
489
|
+
this.#notify(oldest.key, value, "evicted");
|
|
369
490
|
}
|
|
370
491
|
}
|
|
371
492
|
#nextDeadline() {
|
|
@@ -786,7 +907,12 @@ function splitReason(options) {
|
|
|
786
907
|
}
|
|
787
908
|
|
|
788
909
|
class Manager {
|
|
789
|
-
cache
|
|
910
|
+
cache;
|
|
911
|
+
#bounded;
|
|
912
|
+
constructor(maxSize) {
|
|
913
|
+
this.#bounded = maxSize !== undefined;
|
|
914
|
+
this.cache = new Collection(null, { maxSize });
|
|
915
|
+
}
|
|
790
916
|
get(id) {
|
|
791
917
|
return this.cache.get(id);
|
|
792
918
|
}
|
|
@@ -822,7 +948,10 @@ class Manager {
|
|
|
822
948
|
}
|
|
823
949
|
set(id, value) {
|
|
824
950
|
this.#markDirty(id);
|
|
825
|
-
this
|
|
951
|
+
if (this.#bounded)
|
|
952
|
+
this.cache.set(id, value);
|
|
953
|
+
else
|
|
954
|
+
this.cache.setWithoutTTL(id, value);
|
|
826
955
|
return this;
|
|
827
956
|
}
|
|
828
957
|
delete(id) {
|
|
@@ -852,8 +981,8 @@ class Manager {
|
|
|
852
981
|
class ResourceManager extends Manager {
|
|
853
982
|
#fetcher;
|
|
854
983
|
#key;
|
|
855
|
-
constructor(fetcher, key) {
|
|
856
|
-
super();
|
|
984
|
+
constructor(fetcher, key, maxSize) {
|
|
985
|
+
super(maxSize);
|
|
857
986
|
if (typeof fetcher !== "function" || typeof key !== "function")
|
|
858
987
|
throw new TypeError("ResourceManager requires fetcher and key functions.");
|
|
859
988
|
this.#fetcher = fetcher;
|
|
@@ -863,7 +992,7 @@ class ResourceManager extends Manager {
|
|
|
863
992
|
return this.get(id) ?? this.fetch(id);
|
|
864
993
|
}
|
|
865
994
|
fetch(id) {
|
|
866
|
-
return this.fetchOnce(id, () => this.#fetcher(id));
|
|
995
|
+
return this.fetchOnce(id, () => this.#fetcher(id), (value) => this.upsert(value));
|
|
867
996
|
}
|
|
868
997
|
async fetchMany(ids) {
|
|
869
998
|
return Promise.all([...ids].map((id) => this.resolve(id)));
|
|
@@ -886,7 +1015,7 @@ class ResourceManager extends Manager {
|
|
|
886
1015
|
// packages/rest/package.json
|
|
887
1016
|
var package_default = {
|
|
888
1017
|
name: "@lunibee/rest",
|
|
889
|
-
version: "0.3.
|
|
1018
|
+
version: "0.3.2",
|
|
890
1019
|
type: "module",
|
|
891
1020
|
module: "./src/index.ts",
|
|
892
1021
|
types: "./src/index.ts",
|
|
@@ -996,6 +1125,139 @@ function snowflake(value, field) {
|
|
|
996
1125
|
throw new TypeError(`${field} must be a valid Discord snowflake.`);
|
|
997
1126
|
return value;
|
|
998
1127
|
}
|
|
1128
|
+
// packages/rest/src/redis.ts
|
|
1129
|
+
var LUA_PRELUDE = `
|
|
1130
|
+
local function now_ms()
|
|
1131
|
+
local t = redis.call('TIME')
|
|
1132
|
+
return tonumber(t[1]) * 1000 + math.floor(tonumber(t[2]) / 1000)
|
|
1133
|
+
end
|
|
1134
|
+
local function load(key)
|
|
1135
|
+
local raw = redis.call('GET', key)
|
|
1136
|
+
if not raw then return nil end
|
|
1137
|
+
local ok, s = pcall(cjson.decode, raw)
|
|
1138
|
+
if ok and type(s) == 'table' and type(s.resetAt) == 'number'
|
|
1139
|
+
and type(s.remaining) == 'number' then return s end
|
|
1140
|
+
return nil
|
|
1141
|
+
end
|
|
1142
|
+
local function save(key, s, now, linger)
|
|
1143
|
+
local ttl = math.max(1, math.ceil(s.resetAt - now)) + linger
|
|
1144
|
+
redis.call('SET', key, cjson.encode(s), 'PX', ttl)
|
|
1145
|
+
end
|
|
1146
|
+
`;
|
|
1147
|
+
var RESERVE_SCRIPT = `${LUA_PRELUDE}
|
|
1148
|
+
local now = now_ms()
|
|
1149
|
+
local glimit, gwindow = tonumber(ARGV[4]) or 0, tonumber(ARGV[5]) or 1000
|
|
1150
|
+
if #KEYS > 1 then
|
|
1151
|
+
local g = tonumber(redis.call('GET', KEYS[2]) or '0') or 0
|
|
1152
|
+
if g > now then return {0, math.ceil(g - now), 'global'} end
|
|
1153
|
+
end
|
|
1154
|
+
if #KEYS < 3 then glimit = 0 end
|
|
1155
|
+
-- A sliding log of send times: at most glimit in any gwindow span.
|
|
1156
|
+
if glimit > 0 then
|
|
1157
|
+
redis.call('ZREMRANGEBYSCORE', KEYS[3], '-inf', now - gwindow)
|
|
1158
|
+
if redis.call('ZCARD', KEYS[3]) >= glimit then
|
|
1159
|
+
local oldest = redis.call('ZRANGE', KEYS[3], 0, 0, 'WITHSCORES')
|
|
1160
|
+
return {0, math.max(1, tonumber(oldest[2]) + gwindow - now + 1), 'global'}
|
|
1161
|
+
end
|
|
1162
|
+
end
|
|
1163
|
+
local function count()
|
|
1164
|
+
if glimit > 0 then
|
|
1165
|
+
local seq = redis.call('ZCARD', KEYS[3])
|
|
1166
|
+
redis.call('ZADD', KEYS[3], now, now .. ':' .. seq)
|
|
1167
|
+
redis.call('PEXPIRE', KEYS[3], gwindow + 1000)
|
|
1168
|
+
end
|
|
1169
|
+
end
|
|
1170
|
+
local probe, poll, linger = tonumber(ARGV[1]), tonumber(ARGV[2]), tonumber(ARGV[3])
|
|
1171
|
+
local s = load(KEYS[1])
|
|
1172
|
+
if s and s.resetAt > now then
|
|
1173
|
+
if s.remaining > 0 then
|
|
1174
|
+
s.remaining = s.remaining - 1
|
|
1175
|
+
save(KEYS[1], s, now, linger)
|
|
1176
|
+
count()
|
|
1177
|
+
return {1, s.resetAt, 1}
|
|
1178
|
+
end
|
|
1179
|
+
local wait = s.resetAt - now
|
|
1180
|
+
if s.provisional then wait = math.min(wait, poll) end
|
|
1181
|
+
local reason = 'bucket'
|
|
1182
|
+
if s.probe then reason = 'probe' end
|
|
1183
|
+
return {0, math.ceil(wait), reason}
|
|
1184
|
+
end
|
|
1185
|
+
local resetAt = now + probe
|
|
1186
|
+
if s and type(s.limit) == 'number' and s.limit > 0 then
|
|
1187
|
+
save(KEYS[1], {remaining = s.limit - 1, resetAt = resetAt, limit = s.limit, provisional = true}, now, linger)
|
|
1188
|
+
count()
|
|
1189
|
+
return {1, resetAt, 1}
|
|
1190
|
+
end
|
|
1191
|
+
save(KEYS[1], {remaining = 0, resetAt = resetAt, provisional = true, probe = true}, now, 0)
|
|
1192
|
+
count()
|
|
1193
|
+
return {1, resetAt, 0}
|
|
1194
|
+
`;
|
|
1195
|
+
var RECONCILE_SCRIPT = `${LUA_PRELUDE}
|
|
1196
|
+
local now = now_ms()
|
|
1197
|
+
local rem, after, limit = tonumber(ARGV[1]), tonumber(ARGV[2]), tonumber(ARGV[3])
|
|
1198
|
+
local win, retry, linger = tonumber(ARGV[4]), tonumber(ARGV[5]), tonumber(ARGV[6])
|
|
1199
|
+
local tol = 50
|
|
1200
|
+
local incoming = nil
|
|
1201
|
+
if after then incoming = math.ceil(now + after) end
|
|
1202
|
+
local s = load(KEYS[1])
|
|
1203
|
+
local n
|
|
1204
|
+
if s and s.resetAt > now and not s.probe then
|
|
1205
|
+
n = s
|
|
1206
|
+
local stale = win and n.window and win < n.window - tol
|
|
1207
|
+
if not stale then
|
|
1208
|
+
if rem then n.remaining = math.min(n.remaining, rem) end
|
|
1209
|
+
if incoming then
|
|
1210
|
+
local newer = win and n.window and win > n.window + tol
|
|
1211
|
+
if n.provisional or newer then n.resetAt = incoming
|
|
1212
|
+
else n.resetAt = math.max(n.resetAt, incoming) end
|
|
1213
|
+
n.provisional = nil
|
|
1214
|
+
end
|
|
1215
|
+
if win then n.window = math.max(n.window or 0, win) end
|
|
1216
|
+
end
|
|
1217
|
+
else
|
|
1218
|
+
if not rem and not retry then
|
|
1219
|
+
if s and s.probe then redis.call('DEL', KEYS[1]) end
|
|
1220
|
+
return 0
|
|
1221
|
+
end
|
|
1222
|
+
n = {remaining = rem or 0, resetAt = incoming or now}
|
|
1223
|
+
if s and type(s.limit) == 'number' then n.limit = s.limit end
|
|
1224
|
+
if win then n.window = win end
|
|
1225
|
+
end
|
|
1226
|
+
if limit and limit > 0 then n.limit = limit end
|
|
1227
|
+
if retry then
|
|
1228
|
+
n.remaining = 0
|
|
1229
|
+
n.resetAt = math.max(n.resetAt, math.ceil(now + retry))
|
|
1230
|
+
n.provisional = nil
|
|
1231
|
+
end
|
|
1232
|
+
save(KEYS[1], n, now, linger)
|
|
1233
|
+
return 1
|
|
1234
|
+
`;
|
|
1235
|
+
var EXTEND_GLOBAL_SCRIPT = `${LUA_PRELUDE}
|
|
1236
|
+
local now = now_ms()
|
|
1237
|
+
local target = math.ceil(now + tonumber(ARGV[1]))
|
|
1238
|
+
local cur = tonumber(redis.call('GET', KEYS[1]) or '0') or 0
|
|
1239
|
+
if target > cur then
|
|
1240
|
+
redis.call('SET', KEYS[1], tostring(target), 'PX', math.max(1, target - now))
|
|
1241
|
+
return target - now
|
|
1242
|
+
end
|
|
1243
|
+
return math.max(0, cur - now)
|
|
1244
|
+
`;
|
|
1245
|
+
var RELEASE_SCRIPT = `${LUA_PRELUDE}
|
|
1246
|
+
local s = load(KEYS[1])
|
|
1247
|
+
if not s or s.resetAt ~= tonumber(ARGV[1]) then return 0 end
|
|
1248
|
+
if s.probe then
|
|
1249
|
+
redis.call('DEL', KEYS[1])
|
|
1250
|
+
return 1
|
|
1251
|
+
end
|
|
1252
|
+
if ARGV[2] == '1' then
|
|
1253
|
+
local cap = s.remaining + 1
|
|
1254
|
+
if type(s.limit) == 'number' then cap = math.min(cap, s.limit) end
|
|
1255
|
+
s.remaining = cap
|
|
1256
|
+
redis.call('SET', KEYS[1], cjson.encode(s), 'KEEPTTL')
|
|
1257
|
+
return 1
|
|
1258
|
+
end
|
|
1259
|
+
return 0
|
|
1260
|
+
`;
|
|
999
1261
|
|
|
1000
1262
|
// packages/rest/src/index.ts
|
|
1001
1263
|
var LIBRARY_VERSION = package_default.version;
|
|
@@ -1008,7 +1270,8 @@ var REQUEST_DATA_KEYS = new Set([
|
|
|
1008
1270
|
"headers",
|
|
1009
1271
|
"reason",
|
|
1010
1272
|
"auth",
|
|
1011
|
-
"signal"
|
|
1273
|
+
"signal",
|
|
1274
|
+
"maxQueueWait"
|
|
1012
1275
|
]);
|
|
1013
1276
|
|
|
1014
1277
|
// packages/types/src/channel-kind.ts
|
|
@@ -1157,8 +1420,9 @@ class Channel extends BaseStructure {
|
|
|
1157
1420
|
rateLimitPerUser;
|
|
1158
1421
|
position;
|
|
1159
1422
|
permissionOverwrites;
|
|
1423
|
+
partial;
|
|
1160
1424
|
#context;
|
|
1161
|
-
constructor(data, context) {
|
|
1425
|
+
constructor(data, context, options = {}) {
|
|
1162
1426
|
super(data.id);
|
|
1163
1427
|
if (!Number.isInteger(data.type) || data.type < 0)
|
|
1164
1428
|
throw new RangeError("A Discord channel requires a valid channel type.");
|
|
@@ -1171,6 +1435,7 @@ class Channel extends BaseStructure {
|
|
|
1171
1435
|
this.rateLimitPerUser = data.rate_limit_per_user;
|
|
1172
1436
|
this.position = data.position;
|
|
1173
1437
|
this.permissionOverwrites = (data.permission_overwrites ?? []).map((overwrite) => ({ ...overwrite }));
|
|
1438
|
+
this.partial = options.partial ?? false;
|
|
1174
1439
|
this.#context = context;
|
|
1175
1440
|
}
|
|
1176
1441
|
send(options) {
|
|
@@ -1361,7 +1626,7 @@ class Guild extends BaseStructure {
|
|
|
1361
1626
|
}
|
|
1362
1627
|
}
|
|
1363
1628
|
|
|
1364
|
-
// packages/
|
|
1629
|
+
// packages/structures/src/permissions.ts
|
|
1365
1630
|
var Permission = {
|
|
1366
1631
|
createInstantInvite: 1n << 0n,
|
|
1367
1632
|
kickMembers: 1n << 1n,
|
|
@@ -1643,6 +1908,15 @@ class PermissionSet {
|
|
|
1643
1908
|
get useExternalApps() {
|
|
1644
1909
|
return (this.bitfield & Permission.useExternalApps) === Permission.useExternalApps;
|
|
1645
1910
|
}
|
|
1911
|
+
get setVoiceChannelStatus() {
|
|
1912
|
+
return (this.bitfield & Permission.setVoiceChannelStatus) === Permission.setVoiceChannelStatus;
|
|
1913
|
+
}
|
|
1914
|
+
get pinMessages() {
|
|
1915
|
+
return (this.bitfield & Permission.pinMessages) === Permission.pinMessages;
|
|
1916
|
+
}
|
|
1917
|
+
get bypassSlowmode() {
|
|
1918
|
+
return (this.bitfield & Permission.bypassSlowmode) === Permission.bypassSlowmode;
|
|
1919
|
+
}
|
|
1646
1920
|
has(...permissions) {
|
|
1647
1921
|
if (permissions.length === 1) {
|
|
1648
1922
|
const p = permissions[0];
|
|
@@ -1745,60 +2019,7 @@ class PermissionsBitField extends PermissionSet {
|
|
|
1745
2019
|
}
|
|
1746
2020
|
}
|
|
1747
2021
|
var ALL_PERMISSIONS = Object.values(Permission).reduce((bits, bit) => bits | bit, 0n);
|
|
1748
|
-
// packages/builders/src/components.ts
|
|
1749
|
-
var IS_COMPONENTS_V2 = 1 << 15;
|
|
1750
|
-
// packages/builders/src/commands.ts
|
|
1751
|
-
var MAX_SAFE = Number.MAX_SAFE_INTEGER;
|
|
1752
|
-
// packages/utils/src/args.ts
|
|
1753
|
-
var TRUE_WORDS = new Set([
|
|
1754
|
-
"true",
|
|
1755
|
-
"yes",
|
|
1756
|
-
"y",
|
|
1757
|
-
"on",
|
|
1758
|
-
"1",
|
|
1759
|
-
"enable",
|
|
1760
|
-
"enabled"
|
|
1761
|
-
]);
|
|
1762
|
-
var FALSE_WORDS = new Set([
|
|
1763
|
-
"false",
|
|
1764
|
-
"no",
|
|
1765
|
-
"n",
|
|
1766
|
-
"off",
|
|
1767
|
-
"0",
|
|
1768
|
-
"disable",
|
|
1769
|
-
"disabled"
|
|
1770
|
-
]);
|
|
1771
|
-
// packages/ws/src/close-codes.ts
|
|
1772
|
-
var GatewayCloseCodes = {
|
|
1773
|
-
UnknownError: 4000,
|
|
1774
|
-
UnknownOpcode: 4001,
|
|
1775
|
-
DecodeError: 4002,
|
|
1776
|
-
NotAuthenticated: 4003,
|
|
1777
|
-
AuthenticationFailed: 4004,
|
|
1778
|
-
AlreadyAuthenticated: 4005,
|
|
1779
|
-
InvalidSeq: 4007,
|
|
1780
|
-
RateLimited: 4008,
|
|
1781
|
-
SessionTimedOut: 4009,
|
|
1782
|
-
InvalidShard: 4010,
|
|
1783
|
-
ShardingRequired: 4011,
|
|
1784
|
-
InvalidAPIVersion: 4012,
|
|
1785
|
-
InvalidIntents: 4013,
|
|
1786
|
-
DisallowedIntents: 4014
|
|
1787
|
-
};
|
|
1788
2022
|
|
|
1789
|
-
// packages/ws/src/reconnect.ts
|
|
1790
|
-
var FATAL_CLOSE_CODES = [
|
|
1791
|
-
GatewayCloseCodes.AuthenticationFailed,
|
|
1792
|
-
GatewayCloseCodes.InvalidShard,
|
|
1793
|
-
GatewayCloseCodes.ShardingRequired,
|
|
1794
|
-
GatewayCloseCodes.InvalidAPIVersion,
|
|
1795
|
-
GatewayCloseCodes.InvalidIntents,
|
|
1796
|
-
GatewayCloseCodes.DisallowedIntents
|
|
1797
|
-
];
|
|
1798
|
-
var IDENTIFY_CLOSE_CODES = [
|
|
1799
|
-
GatewayCloseCodes.InvalidSeq,
|
|
1800
|
-
GatewayCloseCodes.SessionTimedOut
|
|
1801
|
-
];
|
|
1802
2023
|
// packages/structures/src/resources.ts
|
|
1803
2024
|
function toDateOrNull(value) {
|
|
1804
2025
|
if (!value)
|
|
@@ -1954,7 +2175,7 @@ class TextChannel extends Channel {
|
|
|
1954
2175
|
return `<#${this.id}>`;
|
|
1955
2176
|
}
|
|
1956
2177
|
}
|
|
1957
|
-
class
|
|
2178
|
+
class Emoji extends BaseStructure {
|
|
1958
2179
|
name;
|
|
1959
2180
|
roleIds;
|
|
1960
2181
|
user;
|
|
@@ -2302,7 +2523,7 @@ class Message extends BaseStructure {
|
|
|
2302
2523
|
user: data.member.user ?? data.author,
|
|
2303
2524
|
guild_id: data.guild_id
|
|
2304
2525
|
}, context) : null;
|
|
2305
|
-
this.channel = new Channel({ id: data.channel_id, type: 0, guild_id: data.guild_id }, context);
|
|
2526
|
+
this.channel = context?.cachedChannel?.(data.channel_id) ?? new Channel({ id: data.channel_id, type: 0, guild_id: data.guild_id }, context, { partial: true });
|
|
2306
2527
|
}
|
|
2307
2528
|
get embedsSuppressed() {
|
|
2308
2529
|
return (this.flags & 4) !== 0;
|
|
@@ -2430,18 +2651,41 @@ class Message extends BaseStructure {
|
|
|
2430
2651
|
|
|
2431
2652
|
// packages/managers/src/message.ts
|
|
2432
2653
|
function toAttachments(files) {
|
|
2433
|
-
return files.map((file) => ({
|
|
2654
|
+
return files.map((file) => ("toBuffer" in file) ? { name: file.name, data: file.toBuffer() } : {
|
|
2434
2655
|
name: file.name,
|
|
2435
2656
|
data: typeof file.data === "string" ? new TextEncoder().encode(file.data) : file.data,
|
|
2436
2657
|
contentType: file.contentType
|
|
2437
|
-
})
|
|
2658
|
+
});
|
|
2659
|
+
}
|
|
2660
|
+
function assertAllowedMentions(mentions) {
|
|
2661
|
+
const parse = mentions.parse ?? [];
|
|
2662
|
+
for (const kind of parse)
|
|
2663
|
+
if (!["roles", "users", "everyone"].includes(kind))
|
|
2664
|
+
throw new TypeError(`allowed_mentions.parse has unknown value "${String(kind)}".`);
|
|
2665
|
+
for (const [kind, list] of [
|
|
2666
|
+
["users", mentions.users],
|
|
2667
|
+
["roles", mentions.roles]
|
|
2668
|
+
]) {
|
|
2669
|
+
if (list === undefined)
|
|
2670
|
+
continue;
|
|
2671
|
+
if (!Array.isArray(list) || list.some((id) => typeof id !== "string"))
|
|
2672
|
+
throw new TypeError(`allowed_mentions.${kind} must be an array of ID strings.`);
|
|
2673
|
+
if (list.length > 100)
|
|
2674
|
+
throw new RangeError(`allowed_mentions.${kind} holds at most 100 IDs.`);
|
|
2675
|
+
if (list.length > 0 && parse.includes(kind))
|
|
2676
|
+
throw new TypeError(`allowed_mentions cannot list ${kind} by ID and also parse "${kind}".`);
|
|
2677
|
+
}
|
|
2438
2678
|
}
|
|
2439
2679
|
function toRequest(options, allowedMentions) {
|
|
2440
2680
|
const { files, ...body } = options;
|
|
2441
2681
|
if (allowedMentions !== undefined && body.allowed_mentions === undefined)
|
|
2442
2682
|
body.allowed_mentions = allowedMentions;
|
|
2683
|
+
if (body.allowed_mentions)
|
|
2684
|
+
assertAllowedMentions(body.allowed_mentions);
|
|
2443
2685
|
if (!files?.length)
|
|
2444
2686
|
return body;
|
|
2687
|
+
if (body.attachments === undefined && files.some((f) => f.description))
|
|
2688
|
+
body.attachments = files.map((file, id) => file.description ? { id, description: file.description } : { id });
|
|
2445
2689
|
return {
|
|
2446
2690
|
body,
|
|
2447
2691
|
files: toAttachments(files)
|
|
@@ -2503,12 +2747,14 @@ class ThreadManager {
|
|
|
2503
2747
|
#rest;
|
|
2504
2748
|
#context;
|
|
2505
2749
|
#channelId;
|
|
2506
|
-
|
|
2750
|
+
#allowedMentions;
|
|
2751
|
+
constructor(rest, context, channelId, allowedMentions) {
|
|
2507
2752
|
if (!channelId)
|
|
2508
2753
|
throw new TypeError("Channel ID is required.");
|
|
2509
2754
|
this.#rest = rest;
|
|
2510
2755
|
this.#context = context;
|
|
2511
2756
|
this.#channelId = channelId;
|
|
2757
|
+
this.#allowedMentions = allowedMentions;
|
|
2512
2758
|
}
|
|
2513
2759
|
async createFromMessage(messageId, options) {
|
|
2514
2760
|
const data = await this.#rest.post(Routes.messageThread(this.#channelId, messageId), {
|
|
@@ -2530,14 +2776,17 @@ class ThreadManager {
|
|
|
2530
2776
|
}
|
|
2531
2777
|
async createForumPost(options) {
|
|
2532
2778
|
const { message, appliedTags, reason, ...thread } = options;
|
|
2533
|
-
const
|
|
2779
|
+
const request = toRequest(message, this.#allowedMentions);
|
|
2780
|
+
const withFiles = "body" in request && "files" in request;
|
|
2781
|
+
const content = withFiles ? request.body : request;
|
|
2782
|
+
const files = withFiles ? request.files : undefined;
|
|
2534
2783
|
const data = await this.#rest.post(Routes.channelThreads(this.#channelId), {
|
|
2535
2784
|
name: thread.name,
|
|
2536
2785
|
auto_archive_duration: thread.autoArchiveDuration,
|
|
2537
2786
|
rate_limit_per_user: thread.rateLimitPerUser,
|
|
2538
2787
|
applied_tags: appliedTags,
|
|
2539
2788
|
message: content
|
|
2540
|
-
}, { files
|
|
2789
|
+
}, { files, reason });
|
|
2541
2790
|
return createChannel(data, this.#context);
|
|
2542
2791
|
}
|
|
2543
2792
|
async fetchArchived(scope, options = {}) {
|
|
@@ -2631,7 +2880,7 @@ class EmojiManager extends Manager {
|
|
|
2631
2880
|
this.#guildId = guildId;
|
|
2632
2881
|
}
|
|
2633
2882
|
fetch(emojiId) {
|
|
2634
|
-
return this.fetchOnce(emojiId, async () => new
|
|
2883
|
+
return this.fetchOnce(emojiId, async () => new Emoji(await this.#rest.get(Routes.guildEmoji(this.#guildId, emojiId))), (emoji) => this.#merge(emojiId, emoji));
|
|
2635
2884
|
}
|
|
2636
2885
|
async fetchAll() {
|
|
2637
2886
|
const data = await this.#rest.get(Routes.guildEmoji(this.#guildId));
|
|
@@ -2653,7 +2902,7 @@ class EmojiManager extends Manager {
|
|
|
2653
2902
|
}
|
|
2654
2903
|
upsert(data) {
|
|
2655
2904
|
const key = data.id != null ? data.id : `unicode:${data.name ?? ""}`;
|
|
2656
|
-
return this.#merge(key, new
|
|
2905
|
+
return this.#merge(key, new Emoji(data));
|
|
2657
2906
|
}
|
|
2658
2907
|
#merge(key, emoji) {
|
|
2659
2908
|
const existing = this.get(key);
|
|
@@ -2871,8 +3120,8 @@ class GuildMemberManager extends ResourceManager {
|
|
|
2871
3120
|
guildId;
|
|
2872
3121
|
constructor(guildId, rest, context = () => {
|
|
2873
3122
|
return;
|
|
2874
|
-
}) {
|
|
2875
|
-
super((id) => rest.get(Routes.guildMember(guildId, id)).then((data) => new GuildMember({ ...data, guild_id: guildId }, context())), (member) => member.user.id);
|
|
3123
|
+
}, maxSize) {
|
|
3124
|
+
super((id) => rest.get(Routes.guildMember(guildId, id)).then((data) => new GuildMember({ ...data, guild_id: guildId }, context())), (member) => member.user.id, maxSize);
|
|
2876
3125
|
this.guildId = guildId;
|
|
2877
3126
|
this.#rest = rest;
|
|
2878
3127
|
this.#context = context;
|
|
@@ -3202,9 +3451,11 @@ class GuildManager extends ResourceManager {
|
|
|
3202
3451
|
map.set(guildId, manager = create());
|
|
3203
3452
|
return manager;
|
|
3204
3453
|
}
|
|
3205
|
-
|
|
3454
|
+
#maxMembers;
|
|
3455
|
+
constructor(rest, options = {}) {
|
|
3206
3456
|
super(async (id) => new Guild(await rest.get(Routes.guild(id))), (guild) => guild.id);
|
|
3207
3457
|
this.#rest = rest;
|
|
3458
|
+
this.#maxMembers = options.maxMembers;
|
|
3208
3459
|
}
|
|
3209
3460
|
bans(guildId) {
|
|
3210
3461
|
let manager = this.#bans.get(guildId);
|
|
@@ -3221,7 +3472,7 @@ class GuildManager extends ResourceManager {
|
|
|
3221
3472
|
members(guildId) {
|
|
3222
3473
|
let manager = this.#members.get(guildId);
|
|
3223
3474
|
if (!manager)
|
|
3224
|
-
this.#members.set(guildId, manager = new GuildMemberManager(guildId, this.#rest, () => this.#context));
|
|
3475
|
+
this.#members.set(guildId, manager = new GuildMemberManager(guildId, this.#rest, () => this.#context, this.#maxMembers));
|
|
3225
3476
|
return manager;
|
|
3226
3477
|
}
|
|
3227
3478
|
roles(guildId) {
|
|
@@ -3265,9 +3516,13 @@ class GuildManager extends ResourceManager {
|
|
|
3265
3516
|
const existing = this.get(guild.id);
|
|
3266
3517
|
if (!existing)
|
|
3267
3518
|
return this.upsert(guild);
|
|
3268
|
-
|
|
3519
|
+
const from = guild;
|
|
3520
|
+
const into = existing;
|
|
3521
|
+
for (const key of Object.keys(from)) {
|
|
3522
|
+
const value = from[key];
|
|
3269
3523
|
if (value !== undefined)
|
|
3270
|
-
|
|
3524
|
+
into[key] = value;
|
|
3525
|
+
}
|
|
3271
3526
|
return existing;
|
|
3272
3527
|
}
|
|
3273
3528
|
delete(id) {
|
|
@@ -3435,6 +3690,10 @@ var AuditLogEvent = {
|
|
|
3435
3690
|
AutoModerationBlockMessage: 143
|
|
3436
3691
|
};
|
|
3437
3692
|
// packages/managers/src/application.ts
|
|
3693
|
+
function commandPayload(command) {
|
|
3694
|
+
return "toJSON" in command && typeof command.toJSON === "function" ? command.toJSON() : command;
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3438
3697
|
class ApplicationCommandManager {
|
|
3439
3698
|
#rest;
|
|
3440
3699
|
#applicationId;
|
|
@@ -3446,13 +3705,13 @@ class ApplicationCommandManager {
|
|
|
3446
3705
|
return this.#rest.get(Routes.applicationCommands(this.#applicationId));
|
|
3447
3706
|
}
|
|
3448
3707
|
create(data) {
|
|
3449
|
-
return this.#rest.post(Routes.applicationCommands(this.#applicationId), data);
|
|
3708
|
+
return this.#rest.post(Routes.applicationCommands(this.#applicationId), commandPayload(data));
|
|
3450
3709
|
}
|
|
3451
3710
|
set(commands) {
|
|
3452
|
-
return this.#rest.put(Routes.applicationCommands(this.#applicationId), commands);
|
|
3711
|
+
return this.#rest.put(Routes.applicationCommands(this.#applicationId), commands.map(commandPayload));
|
|
3453
3712
|
}
|
|
3454
3713
|
edit(commandId, data) {
|
|
3455
|
-
return this.#rest.patch(Routes.applicationCommand(this.#applicationId, commandId), data);
|
|
3714
|
+
return this.#rest.patch(Routes.applicationCommand(this.#applicationId, commandId), commandPayload(data));
|
|
3456
3715
|
}
|
|
3457
3716
|
async delete(commandId) {
|
|
3458
3717
|
await this.#rest.delete(Routes.applicationCommand(this.#applicationId, commandId));
|
|
@@ -3461,13 +3720,13 @@ class ApplicationCommandManager {
|
|
|
3461
3720
|
return this.#rest.get(Routes.guildApplicationCommands(this.#applicationId, guildId));
|
|
3462
3721
|
}
|
|
3463
3722
|
createGuild(guildId, data) {
|
|
3464
|
-
return this.#rest.post(Routes.guildApplicationCommands(this.#applicationId, guildId), data);
|
|
3723
|
+
return this.#rest.post(Routes.guildApplicationCommands(this.#applicationId, guildId), commandPayload(data));
|
|
3465
3724
|
}
|
|
3466
3725
|
setGuild(guildId, commands) {
|
|
3467
|
-
return this.#rest.put(Routes.guildApplicationCommands(this.#applicationId, guildId), commands);
|
|
3726
|
+
return this.#rest.put(Routes.guildApplicationCommands(this.#applicationId, guildId), commands.map(commandPayload));
|
|
3468
3727
|
}
|
|
3469
3728
|
editGuild(guildId, commandId, data) {
|
|
3470
|
-
return this.#rest.patch(Routes.guildApplicationCommand(this.#applicationId, guildId, commandId), data);
|
|
3729
|
+
return this.#rest.patch(Routes.guildApplicationCommand(this.#applicationId, guildId, commandId), commandPayload(data));
|
|
3471
3730
|
}
|
|
3472
3731
|
async deleteGuild(guildId, commandId) {
|
|
3473
3732
|
await this.#rest.delete(Routes.guildApplicationCommand(this.#applicationId, guildId, commandId));
|
|
@@ -3515,10 +3774,13 @@ class ChannelManager extends Manager {
|
|
|
3515
3774
|
return manager;
|
|
3516
3775
|
}
|
|
3517
3776
|
permissionOverwrites(channelId) {
|
|
3518
|
-
return new PermissionOverwriteManager(this.#rest, channelId, () =>
|
|
3777
|
+
return new PermissionOverwriteManager(this.#rest, channelId, () => {
|
|
3778
|
+
const channel = this.get(channelId);
|
|
3779
|
+
return channel && !channel.partial ? channel.permissionOverwrites : undefined;
|
|
3780
|
+
});
|
|
3519
3781
|
}
|
|
3520
3782
|
threads(channelId) {
|
|
3521
|
-
return new ThreadManager(this.#rest, this.#context, channelId);
|
|
3783
|
+
return new ThreadManager(this.#rest, this.#context, channelId, this.#allowedMentions);
|
|
3522
3784
|
}
|
|
3523
3785
|
fetch(channelId) {
|
|
3524
3786
|
return this.fetchOnce(channelId, async () => createChannel(await this.#rest.get(Routes.channel(channelId)), this.#context), (channel) => this.#merge(channel));
|
|
@@ -3785,4 +4047,4 @@ export {
|
|
|
3785
4047
|
toRequest
|
|
3786
4048
|
};
|
|
3787
4049
|
|
|
3788
|
-
//# debugId=
|
|
4050
|
+
//# debugId=FBBCAAAFD8D05B9864756E2164756E21
|