@discordkit/core 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/requests/DiscordSession.d.ts +9 -0
- package/dist/requests/DiscordSession.js +213 -0
- package/dist/requests/DiscordSession.js.map +1 -1
- package/dist/requests/index.d.ts +1 -0
- package/dist/requests/index.js +1 -0
- package/dist/requests/index.js.map +1 -1
- package/dist/requests/request.js +5 -10
- package/dist/requests/request.js.map +1 -1
- package/dist/requests/verifyKey.d.ts +10 -0
- package/dist/requests/verifyKey.js +91 -0
- package/dist/requests/verifyKey.js.map +1 -0
- package/dist/utils/sleep.d.ts +4 -0
- package/dist/utils/sleep.js +5 -0
- package/dist/utils/sleep.js.map +1 -0
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ export declare const endpoint = "https://discord.com/api/v10/";
|
|
|
3
3
|
export declare class DiscordSession {
|
|
4
4
|
#private;
|
|
5
5
|
endpoint: string;
|
|
6
|
+
maxRetries: number;
|
|
6
7
|
get ready(): boolean;
|
|
7
8
|
constructor(authToken?: `${`Bot` | `Bearer`} ${string}` | null);
|
|
8
9
|
/**
|
|
@@ -12,5 +13,13 @@ export declare class DiscordSession {
|
|
|
12
13
|
setToken: (token: `${`Bot` | `Bearer`} ${string}`) => this;
|
|
13
14
|
clearSession: () => this;
|
|
14
15
|
getSession: () => string;
|
|
16
|
+
/**
|
|
17
|
+
* Queue a request to be processed with rate limiting
|
|
18
|
+
*/
|
|
19
|
+
queueRequest: (resource: URL, method: string, body?: string | null) => Promise<Response>;
|
|
20
|
+
/**
|
|
21
|
+
* Get current queue size (useful for monitoring)
|
|
22
|
+
*/
|
|
23
|
+
getQueueSize: () => number;
|
|
15
24
|
}
|
|
16
25
|
export declare const discord: DiscordSession;
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
import { sleep } from "../utils/sleep.js";
|
|
1
2
|
export const endpoint = `https://discord.com/api/v10/`;
|
|
2
3
|
/** @internal */
|
|
3
4
|
export class DiscordSession {
|
|
4
5
|
endpoint = endpoint;
|
|
6
|
+
maxRetries = 5;
|
|
5
7
|
#authToken = null;
|
|
8
|
+
// Rate limit tracking
|
|
9
|
+
#buckets = new Map();
|
|
10
|
+
#globalReset = 0; // Epoch timestamp when global limit resets
|
|
11
|
+
#requestQueue = [];
|
|
12
|
+
#processingQueue = false;
|
|
13
|
+
// Global rate limit: 50 requests per second
|
|
14
|
+
#globalLimit = 50;
|
|
15
|
+
#globalWindow = 1000; // 1 second in ms
|
|
16
|
+
#globalRequestTimestamps = [];
|
|
17
|
+
// Invalid request tracking: 10,000 per 10 minutes
|
|
18
|
+
#invalidRequests = {
|
|
19
|
+
count: 0,
|
|
20
|
+
windowStart: Date.now()
|
|
21
|
+
};
|
|
22
|
+
#invalidRequestLimit = 10000;
|
|
23
|
+
#invalidRequestWindow = 10 * 60 * 1000; // 10 minutes in ms
|
|
6
24
|
get ready() {
|
|
7
25
|
return Boolean(this.#authToken);
|
|
8
26
|
}
|
|
@@ -28,6 +46,14 @@ export class DiscordSession {
|
|
|
28
46
|
};
|
|
29
47
|
clearSession = () => {
|
|
30
48
|
this.#authToken = null;
|
|
49
|
+
this.#buckets.clear();
|
|
50
|
+
this.#globalReset = 0;
|
|
51
|
+
this.#requestQueue = [];
|
|
52
|
+
this.#globalRequestTimestamps = [];
|
|
53
|
+
this.#invalidRequests = {
|
|
54
|
+
count: 0,
|
|
55
|
+
windowStart: Date.now()
|
|
56
|
+
};
|
|
31
57
|
return this;
|
|
32
58
|
};
|
|
33
59
|
getSession = () => {
|
|
@@ -37,6 +63,193 @@ export class DiscordSession {
|
|
|
37
63
|
}
|
|
38
64
|
return token;
|
|
39
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* Queue a request to be processed with rate limiting
|
|
68
|
+
*/
|
|
69
|
+
queueRequest = async (resource, method, body) => {
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
this.#requestQueue.push({
|
|
72
|
+
resource,
|
|
73
|
+
method,
|
|
74
|
+
body,
|
|
75
|
+
resolve,
|
|
76
|
+
reject
|
|
77
|
+
});
|
|
78
|
+
// Start processing if not already running
|
|
79
|
+
void this.#processQueue(); // This will return early if already processing
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Process the request queue with rate limiting
|
|
84
|
+
*/
|
|
85
|
+
#processQueue = async () => {
|
|
86
|
+
if (this.#processingQueue)
|
|
87
|
+
return;
|
|
88
|
+
this.#processingQueue = true;
|
|
89
|
+
while (this.#requestQueue.length > 0) {
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
// Check if we're temporarily banned (invalid request limit)
|
|
92
|
+
if (this.#isTemporarilyBanned()) {
|
|
93
|
+
const waitTime = this.#invalidRequestWindow -
|
|
94
|
+
(now - this.#invalidRequests.windowStart);
|
|
95
|
+
console.warn(`Temporarily banned from Discord API. Waiting ${Math.ceil(waitTime / 1000)}s`);
|
|
96
|
+
await sleep(waitTime);
|
|
97
|
+
this.#resetInvalidRequestCounter();
|
|
98
|
+
}
|
|
99
|
+
// Check global rate limit (50 req/s)
|
|
100
|
+
await this.#enforceGlobalRateLimit();
|
|
101
|
+
// Check if we're under a global rate limit cooldown
|
|
102
|
+
if (this.#globalReset > now / 1000) {
|
|
103
|
+
const waitTime = (this.#globalReset - now / 1000) * 1000;
|
|
104
|
+
await sleep(waitTime);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const request = this.#requestQueue[0];
|
|
108
|
+
if (typeof request === `undefined`)
|
|
109
|
+
break;
|
|
110
|
+
const bucket = this.#buckets.get(`${request.method}:${request.resource}`);
|
|
111
|
+
if (bucket?.remaining === 0) {
|
|
112
|
+
const resetTime = bucket.reset * 1000; // Convert to ms
|
|
113
|
+
if (resetTime > now) {
|
|
114
|
+
await sleep(resetTime - now);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Execute the request
|
|
118
|
+
this.#requestQueue.shift();
|
|
119
|
+
try {
|
|
120
|
+
const response = await this.#executeRequest(request);
|
|
121
|
+
request.resolve(response);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (error instanceof Error) {
|
|
125
|
+
request.reject(error);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
this.#processingQueue = false;
|
|
130
|
+
// Check if any requests were added while we were processing the last one
|
|
131
|
+
if (this.#requestQueue.length > 0) {
|
|
132
|
+
void this.#processQueue(); // Restart the processor
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Execute a single request and handle rate limit headers
|
|
137
|
+
*/
|
|
138
|
+
#executeRequest = async (request, retryCount = 0) => {
|
|
139
|
+
const token = this.getSession();
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
// Track this request for global rate limiting
|
|
142
|
+
this.#globalRequestTimestamps.push(now);
|
|
143
|
+
const headers = {
|
|
144
|
+
Authorization: token
|
|
145
|
+
};
|
|
146
|
+
if (request.body) {
|
|
147
|
+
headers[`Content-Type`] = `application/json`;
|
|
148
|
+
}
|
|
149
|
+
const response = await fetch(request.resource.toString(), {
|
|
150
|
+
method: request.method,
|
|
151
|
+
body: request.body,
|
|
152
|
+
headers
|
|
153
|
+
});
|
|
154
|
+
// Update rate limit tracking from headers
|
|
155
|
+
this.#updateRateLimits(response);
|
|
156
|
+
// Handle 429 Too Many Requests
|
|
157
|
+
if (response.status === 429) {
|
|
158
|
+
if (retryCount >= this.maxRetries) {
|
|
159
|
+
console.error(`Max retries (${this.maxRetries}) exceeded for ${request.resource}`);
|
|
160
|
+
return response; // Return the 429 response instead of retrying forever
|
|
161
|
+
}
|
|
162
|
+
const retryAfter = response.headers.get(`Retry-After`) ?? `1`;
|
|
163
|
+
const isGlobal = response.headers.get(`X-RateLimit-Global`) === `true`;
|
|
164
|
+
const scope = response.headers.get(`X-RateLimit-Scope`);
|
|
165
|
+
if (isGlobal || scope === `global`) {
|
|
166
|
+
console.warn(`Hit global rate limit`);
|
|
167
|
+
this.#globalReset = now / 1000 + parseFloat(retryAfter);
|
|
168
|
+
}
|
|
169
|
+
// Wait before retrying
|
|
170
|
+
await sleep(parseFloat(retryAfter) * 1000);
|
|
171
|
+
// Retry with incremented counter
|
|
172
|
+
return this.#executeRequest(request, retryCount + 1);
|
|
173
|
+
}
|
|
174
|
+
// Track invalid requests (401, 403, 429 excluding shared scope)
|
|
175
|
+
if ([401, 403].includes(response.status) ||
|
|
176
|
+
(response.status === 429 &&
|
|
177
|
+
response.headers.get(`X-RateLimit-Scope`) !== `shared`)) {
|
|
178
|
+
this.#trackInvalidRequest();
|
|
179
|
+
}
|
|
180
|
+
return response;
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* Update rate limit buckets from response headers
|
|
184
|
+
*/
|
|
185
|
+
#updateRateLimits = (response) => {
|
|
186
|
+
const bucket = response.headers.get(`X-RateLimit-Bucket`);
|
|
187
|
+
const limit = response.headers.get(`X-RateLimit-Limit`);
|
|
188
|
+
const remaining = response.headers.get(`X-RateLimit-Remaining`);
|
|
189
|
+
const reset = response.headers.get(`X-RateLimit-Reset`);
|
|
190
|
+
const resetAfter = response.headers.get(`X-RateLimit-Reset-After`);
|
|
191
|
+
if (bucket && limit && remaining && reset && resetAfter) {
|
|
192
|
+
this.#buckets.set(bucket, {
|
|
193
|
+
limit: parseInt(limit, 10),
|
|
194
|
+
remaining: parseInt(remaining, 10),
|
|
195
|
+
reset: parseFloat(reset),
|
|
196
|
+
resetAfter: parseFloat(resetAfter)
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* Enforce global rate limit of 50 requests per second
|
|
202
|
+
*/
|
|
203
|
+
#enforceGlobalRateLimit = async () => {
|
|
204
|
+
const now = Date.now();
|
|
205
|
+
// Remove timestamps older than 1 second
|
|
206
|
+
this.#globalRequestTimestamps = this.#globalRequestTimestamps.filter((timestamp) => now - timestamp < this.#globalWindow);
|
|
207
|
+
// If we're at the limit, wait
|
|
208
|
+
if (this.#globalRequestTimestamps.length >= this.#globalLimit) {
|
|
209
|
+
const oldestTimestamp = this.#globalRequestTimestamps[0];
|
|
210
|
+
const waitTime = this.#globalWindow - (now - oldestTimestamp);
|
|
211
|
+
if (waitTime > 0) {
|
|
212
|
+
await sleep(waitTime);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* Track invalid requests for Cloudflare ban prevention
|
|
218
|
+
*/
|
|
219
|
+
#trackInvalidRequest = () => {
|
|
220
|
+
const now = Date.now();
|
|
221
|
+
// Reset counter if window has passed
|
|
222
|
+
if (now - this.#invalidRequests.windowStart >= this.#invalidRequestWindow) {
|
|
223
|
+
this.#resetInvalidRequestCounter();
|
|
224
|
+
}
|
|
225
|
+
this.#invalidRequests.count++;
|
|
226
|
+
if (this.#invalidRequests.count >= this.#invalidRequestLimit) {
|
|
227
|
+
console.error(`Approaching invalid request limit! Bot may be temporarily banned.`);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Check if we're temporarily banned
|
|
232
|
+
*/
|
|
233
|
+
#isTemporarilyBanned = () => {
|
|
234
|
+
const now = Date.now();
|
|
235
|
+
if (now - this.#invalidRequests.windowStart < this.#invalidRequestWindow) {
|
|
236
|
+
return this.#invalidRequests.count >= this.#invalidRequestLimit;
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
};
|
|
240
|
+
/**
|
|
241
|
+
* Reset invalid request counter
|
|
242
|
+
*/
|
|
243
|
+
#resetInvalidRequestCounter = () => {
|
|
244
|
+
this.#invalidRequests = {
|
|
245
|
+
count: 0,
|
|
246
|
+
windowStart: Date.now()
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Get current queue size (useful for monitoring)
|
|
251
|
+
*/
|
|
252
|
+
getQueueSize = () => this.#requestQueue.length;
|
|
40
253
|
}
|
|
41
254
|
export const discord = new DiscordSession();
|
|
42
255
|
//# sourceMappingURL=DiscordSession.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiscordSession.js","sourceRoot":"","sources":["../../src/requests/DiscordSession.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"DiscordSession.js","sourceRoot":"","sources":["../../src/requests/DiscordSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,MAAM,CAAC,MAAM,QAAQ,GAAG,8BAA8B,CAAC;AAuBvD,gBAAgB;AAChB,MAAM,OAAO,cAAc;IACzB,QAAQ,GAAW,QAAQ,CAAC;IAC5B,UAAU,GAAW,CAAC,CAAC;IACvB,UAAU,GAAkB,IAAI,CAAC;IAEjC,sBAAsB;IACtB,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC9C,YAAY,GAAW,CAAC,CAAC,CAAC,2CAA2C;IACrE,aAAa,GAAoB,EAAE,CAAC;IACpC,gBAAgB,GAAG,KAAK,CAAC;IAEzB,4CAA4C;IAC5C,YAAY,GAAG,EAAE,CAAC;IAClB,aAAa,GAAG,IAAI,CAAC,CAAC,iBAAiB;IACvC,wBAAwB,GAAa,EAAE,CAAC;IAExC,kDAAkD;IAClD,gBAAgB,GAA0B;QACxC,KAAK,EAAE,CAAC;QACR,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC;IAEF,oBAAoB,GAAG,KAAK,CAAC;IAC7B,qBAAqB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,mBAAmB;IAE3D,IAAI,KAAK;QACP,OAAO,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IAED,YAAY,SAAkD;QAC5D,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,QAAQ,GAAG,CAAC,KAAsC,EAAQ,EAAE;QAC1D,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CACb,+DAA+D,KAAK,EAAE,CACvE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,YAAY,GAAG,GAAS,EAAE;QACxB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,wBAAwB,GAAG,EAAE,CAAC;QACnC,IAAI,CAAC,gBAAgB,GAAG;YACtB,KAAK,EAAE,CAAC;YACR,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;SACxB,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,UAAU,GAAG,GAAW,EAAE;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC;QAE9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF;;OAEG;IACH,YAAY,GAAG,KAAK,EAClB,QAAa,EACb,MAAc,EACd,IAAoB,EACD,EAAE;QACrB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;gBACtB,QAAQ;gBACR,MAAM;gBACN,IAAI;gBACJ,OAAO;gBACP,MAAM;aACP,CAAC,CAAC;YAEH,0CAA0C;YAC1C,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,+CAA+C;QAC5E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF;;OAEG;IACH,aAAa,GAAG,KAAK,IAAmB,EAAE;QACxC,IAAI,IAAI,CAAC,gBAAgB;YAAE,OAAO;QAClC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAE7B,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAEvB,4DAA4D;YAC5D,IAAI,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;gBAChC,MAAM,QAAQ,GACZ,IAAI,CAAC,qBAAqB;oBAC1B,CAAC,GAAG,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;gBAC5C,OAAO,CAAC,IAAI,CACV,gDAAgD,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAC9E,CAAC;gBACF,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACtB,IAAI,CAAC,2BAA2B,EAAE,CAAC;YACrC,CAAC;YAED,qCAAqC;YACrC,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAErC,oDAAoD;YACpD,IAAI,IAAI,CAAC,YAAY,GAAG,GAAG,GAAG,IAAI,EAAE,CAAC;gBACnC,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,YAAY,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;gBACzD,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACtB,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACtC,IAAI,OAAO,OAAO,KAAK,WAAW;gBAAE,MAAM;YAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;YAE1E,IAAI,MAAM,EAAE,SAAS,KAAK,CAAC,EAAE,CAAC;gBAC5B,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,gBAAgB;gBACvD,IAAI,SAAS,GAAG,GAAG,EAAE,CAAC;oBACpB,MAAM,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;YAED,sBAAsB;YACtB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;gBACrD,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;oBAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAE9B,yEAAyE;QACzE,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,wBAAwB;QACrD,CAAC;IACH,CAAC,CAAC;IAEF;;OAEG;IACH,eAAe,GAAG,KAAK,EACrB,OAAsB,EACtB,UAAU,GAAG,CAAC,EACK,EAAE;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,8CAA8C;QAC9C,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAExC,MAAM,OAAO,GAAgB;YAC3B,aAAa,EAAE,KAAK;SACrB,CAAC;QAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;QAC/C,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE;YACxD,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO;SACR,CAAC,CAAC;QAEH,0CAA0C;QAC1C,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAEjC,+BAA+B;QAC/B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,IAAI,UAAU,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBAClC,OAAO,CAAC,KAAK,CACX,gBAAgB,IAAI,CAAC,UAAU,kBAAkB,OAAO,CAAC,QAAQ,EAAE,CACpE,CAAC;gBACF,OAAO,QAAQ,CAAC,CAAC,sDAAsD;YACzE,CAAC;YAED,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC;YAC9D,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,KAAK,MAAM,CAAC;YACvE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YAExD,IAAI,QAAQ,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACnC,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;gBACtC,IAAI,CAAC,YAAY,GAAG,GAAG,GAAG,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YAC1D,CAAC;YAED,uBAAuB;YACvB,MAAM,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;YAE3C,iCAAiC;YACjC,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;QACvD,CAAC;QAED,gEAAgE;QAChE,IACE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;YACpC,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG;gBACtB,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,KAAK,QAAQ,CAAC,EACzD,CAAC;YACD,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9B,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEF;;OAEG;IACH,iBAAiB,GAAG,CAAC,QAAkB,EAAQ,EAAE;QAC/C,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAEnE,IAAI,MAAM,IAAI,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI,UAAU,EAAE,CAAC;YACxD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE;gBACxB,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC1B,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;gBAClC,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC;gBACxB,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;aACnC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IAEF;;OAEG;IACH,uBAAuB,GAAG,KAAK,IAAmB,EAAE;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,wCAAwC;QACxC,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAClE,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,aAAa,CACpD,CAAC;QAEF,8BAA8B;QAC9B,IAAI,IAAI,CAAC,wBAAwB,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC9D,MAAM,eAAe,GAAG,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,GAAG,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC;YAC9D,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACjB,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF;;OAEG;IACH,oBAAoB,GAAG,GAAS,EAAE;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,qCAAqC;QACrC,IAAI,GAAG,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC1E,IAAI,CAAC,2BAA2B,EAAE,CAAC;QACrC,CAAC;QAED,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAE9B,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC7D,OAAO,CAAC,KAAK,CACX,mEAAmE,CACpE,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF;;OAEG;IACH,oBAAoB,GAAG,GAAY,EAAE;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC,gBAAgB,CAAC,KAAK,IAAI,IAAI,CAAC,oBAAoB,CAAC;QAClE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF;;OAEG;IACH,2BAA2B,GAAG,GAAS,EAAE;QACvC,IAAI,CAAC,gBAAgB,GAAG;YACtB,KAAK,EAAE,CAAC;YACR,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;SACxB,CAAC;IACJ,CAAC,CAAC;IAEF;;OAEG;IACH,YAAY,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;CACxD;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC"}
|
package/dist/requests/index.d.ts
CHANGED
package/dist/requests/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/requests/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACxD,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/requests/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACxD,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC"}
|
package/dist/requests/request.js
CHANGED
|
@@ -8,20 +8,15 @@ export const request = async (resource, method = `GET`, body) => {
|
|
|
8
8
|
}
|
|
9
9
|
const json = () => {
|
|
10
10
|
try {
|
|
11
|
-
return body ? JSON.stringify(toSnakeKeys(body)) : body;
|
|
11
|
+
return body ? JSON.stringify(toSnakeKeys(body)) : body;
|
|
12
12
|
}
|
|
13
|
-
catch (
|
|
13
|
+
catch (cause) {
|
|
14
14
|
console.error(`Received malformed request body:\n\n`, { body });
|
|
15
|
-
throw new Error(`Failed to stringify request body!`,
|
|
15
|
+
throw new Error(`Failed to stringify request body!`, { cause });
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
body: json(),
|
|
21
|
-
headers: {
|
|
22
|
-
Authorization: token
|
|
23
|
-
}
|
|
24
|
-
});
|
|
18
|
+
// Queue the request through the rate limiter
|
|
19
|
+
const res = await discord.queueRequest(resource, method, json());
|
|
25
20
|
if (!res.ok) {
|
|
26
21
|
throw new Error(`Request to resource '${resource.toString()}' failed:\n\n${res.statusText}`);
|
|
27
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/requests/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAItD,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAC1B,QAAa,EACb,MAAM,GAAG,KAAK,EACd,IAAkB,EACN,EAAE;IACd,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAEnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,IAAI,GAAG,GAA8B,EAAE;QAC3C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/requests/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAItD,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAC1B,QAAa,EACb,MAAM,GAAG,KAAK,EACd,IAAkB,EACN,EAAE;IACd,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAEnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,IAAI,GAAG,GAA8B,EAAE;QAC3C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACzD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,mCAAmC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC,CAAC;IAEF,6CAA6C;IAC7C,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,wBAAwB,QAAQ,CAAC,QAAQ,EAAE,gBACzC,GAAG,CAAC,UACN,EAAE,CACH,CAAC;IACJ,CAAC;IAED,8CAA8C;IAC9C,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,mBAAmB;QACnB,OAAO;IACT,CAAC;IAED,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACvC,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates a payload from Discord against its signature and key.
|
|
3
|
+
*
|
|
4
|
+
* @param rawBody - The raw payload data
|
|
5
|
+
* @param signature - The signature from the `X-Signature-Ed25519` header
|
|
6
|
+
* @param timestamp - The timestamp from the `X-Signature-Timestamp` header
|
|
7
|
+
* @param clientPublicKey - The public key from the Discord developer dashboard
|
|
8
|
+
* @returns Whether or not validation was successful
|
|
9
|
+
*/
|
|
10
|
+
export declare function verifyKey(rawBody: Uint8Array | ArrayBuffer | Buffer | string, signature: string, timestamp: string, clientPublicKey: string | CryptoKey): Promise<boolean>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the SubtleCrypto interface for the current environment
|
|
3
|
+
*/
|
|
4
|
+
const getSubtleCrypto = () => {
|
|
5
|
+
// Node.js environment
|
|
6
|
+
if (typeof globalThis.crypto !== `undefined`) {
|
|
7
|
+
return globalThis.crypto.subtle;
|
|
8
|
+
}
|
|
9
|
+
// Older Node.js versions
|
|
10
|
+
if (typeof global !== `undefined` && global.crypto?.subtle) {
|
|
11
|
+
return global.crypto.subtle;
|
|
12
|
+
}
|
|
13
|
+
// Browser environment
|
|
14
|
+
if (typeof window !== `undefined` && window.crypto?.subtle) {
|
|
15
|
+
return window.crypto.subtle;
|
|
16
|
+
}
|
|
17
|
+
throw new Error(`SubtleCrypto is not available in this environment`);
|
|
18
|
+
};
|
|
19
|
+
const subtleCrypto = getSubtleCrypto();
|
|
20
|
+
/**
|
|
21
|
+
* Convert various input types to Uint8Array
|
|
22
|
+
*/
|
|
23
|
+
function valueToUint8Array(value, encoding) {
|
|
24
|
+
// Already a Uint8Array
|
|
25
|
+
if (value instanceof Uint8Array) {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
// ArrayBuffer
|
|
29
|
+
if (value instanceof ArrayBuffer) {
|
|
30
|
+
return new Uint8Array(value);
|
|
31
|
+
}
|
|
32
|
+
// Buffer (Node.js)
|
|
33
|
+
if (typeof Buffer !== `undefined` && Buffer.isBuffer(value)) {
|
|
34
|
+
return new Uint8Array(value);
|
|
35
|
+
}
|
|
36
|
+
// String
|
|
37
|
+
if (typeof value === `string`) {
|
|
38
|
+
if (encoding === `hex`) {
|
|
39
|
+
// Convert hex string to Uint8Array
|
|
40
|
+
const matches = value.match(/.{1,2}/g);
|
|
41
|
+
if (!matches) {
|
|
42
|
+
throw new Error(`Invalid hex string`);
|
|
43
|
+
}
|
|
44
|
+
return new Uint8Array(matches.map((byte) => parseInt(byte, 16)));
|
|
45
|
+
}
|
|
46
|
+
// Default to UTF-8 encoding
|
|
47
|
+
const encoder = new TextEncoder();
|
|
48
|
+
return encoder.encode(value);
|
|
49
|
+
}
|
|
50
|
+
throw new Error(`Unsupported value type`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Concatenate multiple Uint8Arrays into a single Uint8Array
|
|
54
|
+
*/
|
|
55
|
+
function concatUint8Arrays(...arrays) {
|
|
56
|
+
const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
57
|
+
const result = new Uint8Array(totalLength);
|
|
58
|
+
let offset = 0;
|
|
59
|
+
for (const arr of arrays) {
|
|
60
|
+
result.set(arr, offset);
|
|
61
|
+
offset += arr.length;
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Validates a payload from Discord against its signature and key.
|
|
67
|
+
*
|
|
68
|
+
* @param rawBody - The raw payload data
|
|
69
|
+
* @param signature - The signature from the `X-Signature-Ed25519` header
|
|
70
|
+
* @param timestamp - The timestamp from the `X-Signature-Timestamp` header
|
|
71
|
+
* @param clientPublicKey - The public key from the Discord developer dashboard
|
|
72
|
+
* @returns Whether or not validation was successful
|
|
73
|
+
*/
|
|
74
|
+
export async function verifyKey(rawBody, signature, timestamp, clientPublicKey) {
|
|
75
|
+
try {
|
|
76
|
+
return await subtleCrypto.verify({
|
|
77
|
+
name: `ed25519`
|
|
78
|
+
}, typeof clientPublicKey === `string`
|
|
79
|
+
? await subtleCrypto.importKey(`raw`, Buffer.from(valueToUint8Array(clientPublicKey, `hex`)), {
|
|
80
|
+
name: `ed25519`,
|
|
81
|
+
namedCurve: `ed25519`
|
|
82
|
+
}, // Type assertion for Ed25519
|
|
83
|
+
false, [`verify`])
|
|
84
|
+
: clientPublicKey, Buffer.from(valueToUint8Array(signature, `hex`)), Buffer.from(concatUint8Arrays(valueToUint8Array(timestamp), valueToUint8Array(rawBody))));
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
console.error(`Signature verification failed:`, err);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=verifyKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifyKey.js","sourceRoot":"","sources":["../../src/requests/verifyKey.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../src/utils/sleep.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAAE,EAAU,EAAiB,EAAE,CACvD,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC"}
|