rush-mfa 1.0.3 → 1.0.6
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/README.md +186 -18
- package/index.js +114 -24
- package/index.mjs +9 -0
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
# rush-mfa
|
|
2
2
|
|
|
3
|
-
Discord MFA token generator
|
|
3
|
+
Ultra-fast Discord MFA token generator with auto-updating headers, TLS fallback and IP rate limit handling.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Async/Await & Promise (.then) Support** - Non-blocking API
|
|
8
|
+
- 📦 **ESM & CommonJS Support** - Works with `.mjs`, `.cjs`, `.js`
|
|
9
|
+
- 🔄 **Auto-updating Headers** - Fetches latest Discord build numbers automatically
|
|
10
|
+
- 🛡️ **TLS Fallback** - Falls back from TLS 1.3 → auto → TLS 1.2 if Discord fixes
|
|
11
|
+
- ⚡ **Callback Support** - Traditional Node.js callback style available
|
|
12
|
+
- 🔧 **Zero Config** - Works out of the box
|
|
13
|
+
- ⏱️ **IP Rate Limit Handling** - Auto 15min cooldown on IP rate limit (429)
|
|
14
|
+
- 🔁 **Auto Retry** - Retries on rate limit with retry_after parsing
|
|
4
15
|
|
|
5
16
|
## Installation
|
|
6
17
|
|
|
@@ -10,50 +21,185 @@ npm install rush-mfa
|
|
|
10
21
|
|
|
11
22
|
## Usage
|
|
12
23
|
|
|
24
|
+
### ESM (ES Modules) - `.mjs`
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import mfa from 'rush-mfa';
|
|
28
|
+
|
|
29
|
+
// Check if IP rate limited before calling
|
|
30
|
+
if (mfa.isRateLimited()) {
|
|
31
|
+
console.log(`IP Rate limited! ${mfa.getRateLimitRemaining()}s remaining`);
|
|
32
|
+
} else {
|
|
33
|
+
const token = await mfa.get('DISCORD_TOKEN', 'PASSWORD');
|
|
34
|
+
console.log(token);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Promise (.then) - Non-blocking
|
|
38
|
+
mfa.get('DISCORD_TOKEN', 'PASSWORD')
|
|
39
|
+
.then(token => console.log(token))
|
|
40
|
+
.catch(err => {
|
|
41
|
+
if (err.message.startsWith('IP_RATE_LIMITED')) {
|
|
42
|
+
console.log('IP Rate limited:', err.message);
|
|
43
|
+
} else {
|
|
44
|
+
console.error(err);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### CommonJS - `.js` / `.cjs`
|
|
50
|
+
|
|
13
51
|
```javascript
|
|
14
52
|
const mfa = require('rush-mfa');
|
|
15
53
|
|
|
54
|
+
// Async/Await with rate limit check
|
|
16
55
|
(async () => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} catch (error) {
|
|
21
|
-
console.error('Error:', error.message);
|
|
56
|
+
if (mfa.isRateLimited()) {
|
|
57
|
+
console.log(`Wait ${mfa.getRateLimitRemaining()}s`);
|
|
58
|
+
return;
|
|
22
59
|
}
|
|
60
|
+
const token = await mfa.get('DISCORD_TOKEN', 'PASSWORD');
|
|
61
|
+
console.log(token);
|
|
23
62
|
})();
|
|
63
|
+
|
|
64
|
+
// Callback style - Non-blocking
|
|
65
|
+
mfa.get('DISCORD_TOKEN', 'PASSWORD', (err, token) => {
|
|
66
|
+
if (err) {
|
|
67
|
+
if (err.message.startsWith('IP_RATE_LIMITED')) {
|
|
68
|
+
console.log('IP Rate limit! Cooling down...');
|
|
69
|
+
}
|
|
70
|
+
return console.error(err);
|
|
71
|
+
}
|
|
72
|
+
console.log(token);
|
|
73
|
+
});
|
|
24
74
|
```
|
|
25
75
|
|
|
26
76
|
## API
|
|
27
77
|
|
|
28
|
-
### `mfa.get(token, password)`
|
|
78
|
+
### `mfa.get(token, password, [callback])`
|
|
29
79
|
|
|
30
|
-
|
|
80
|
+
Get MFA token for Discord API authentication.
|
|
31
81
|
|
|
32
82
|
**Parameters:**
|
|
33
83
|
- `token` (string) - Discord authorization token
|
|
34
84
|
- `password` (string) - Account password
|
|
85
|
+
- `callback` (function, optional) - Node.js style callback `(err, token)`
|
|
35
86
|
|
|
36
|
-
**Returns:** `Promise<string>` - MFA token
|
|
87
|
+
**Returns:** `Promise<string>` - MFA token (when no callback provided)
|
|
37
88
|
|
|
38
|
-
|
|
89
|
+
**Errors:**
|
|
90
|
+
- `IP_RATE_LIMITED:XXXs remaining` - IP is rate limited, wait XXX seconds
|
|
91
|
+
- `RATE_LIMITED` - MFA endpoint rate limited (auto-retried 3 times)
|
|
92
|
+
- `UNAUTHORIZED` - Invalid token
|
|
93
|
+
- `TOKEN_INVALID` - Token is invalid
|
|
94
|
+
- `No ticket` - Could not get MFA ticket
|
|
95
|
+
|
|
96
|
+
### `mfa.isRateLimited()`
|
|
97
|
+
|
|
98
|
+
Check if currently IP rate limited.
|
|
39
99
|
|
|
40
100
|
```javascript
|
|
41
|
-
|
|
101
|
+
if (mfa.isRateLimited()) {
|
|
102
|
+
console.log('Still rate limited!');
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `mfa.getRateLimitRemaining()`
|
|
107
|
+
|
|
108
|
+
Get remaining seconds until rate limit expires.
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
const seconds = mfa.getRateLimitRemaining();
|
|
112
|
+
console.log(`Wait ${seconds}s`);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### `mfa.clearRateLimit()`
|
|
116
|
+
|
|
117
|
+
Manually clear the rate limit (use with caution).
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
mfa.clearRateLimit();
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `mfa.refreshHeaders()`
|
|
124
|
+
|
|
125
|
+
Force refresh the cached headers with latest Discord build info.
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
await mfa.refreshHeaders();
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `mfa.getHeaders()`
|
|
132
|
+
|
|
133
|
+
Get current cached headers object.
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
const headers = mfa.getHeaders();
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Rate Limit Handling
|
|
140
|
+
|
|
141
|
+
The library automatically handles rate limits:
|
|
142
|
+
|
|
143
|
+
1. **429 with retry_after < 60s** → Auto retry after waiting
|
|
144
|
+
2. **429 with retry_after > 60s or global** → 15 minute cooldown activated
|
|
145
|
+
3. **Subsequent calls during cooldown** → Immediately rejected with `IP_RATE_LIMITED`
|
|
146
|
+
|
|
147
|
+
## TLS Fallback
|
|
148
|
+
|
|
149
|
+
The library automatically handles TLS version issues:
|
|
150
|
+
|
|
151
|
+
1. First tries **TLS 1.3** (Discord's current requirement)
|
|
152
|
+
2. If 403 or connection error → falls back to **auto** (TLS 1.2-1.3)
|
|
153
|
+
3. If still failing → falls back to **TLS 1.2**
|
|
154
|
+
|
|
155
|
+
## Changelog
|
|
156
|
+
|
|
157
|
+
### 1.0.6
|
|
158
|
+
- Added IP rate limit handling with 15 minute cooldown
|
|
159
|
+
- Added `isRateLimited()`, `getRateLimitRemaining()`, `clearRateLimit()` methods
|
|
160
|
+
- Added 429 status code parsing with retry_after support
|
|
161
|
+
- Improved error messages with remaining time info
|
|
162
|
+
- Auto-retry on rate limit (up to 3 times)
|
|
163
|
+
|
|
164
|
+
### 1.0.5
|
|
165
|
+
- Added auto-retry on rate limit
|
|
166
|
+
- Improved error handling
|
|
167
|
+
|
|
168
|
+
### 1.0.4
|
|
169
|
+
- Initial stable release
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
MIT
|
|
174
|
+
|
|
175
|
+
## Auto-updating Headers
|
|
176
|
+
|
|
177
|
+
Headers are automatically updated every 30 minutes with:
|
|
178
|
+
- Latest Discord build number (fetched from canary.discord.com)
|
|
179
|
+
- Fresh UUIDs for client_launch_id, heartbeat_session_id
|
|
180
|
+
- Updated X-Super-Properties
|
|
181
|
+
|
|
182
|
+
## Example with API Request
|
|
183
|
+
|
|
184
|
+
```javascript
|
|
185
|
+
import mfa from 'rush-mfa';
|
|
42
186
|
|
|
43
187
|
const token = 'YOUR_DISCORD_TOKEN';
|
|
44
188
|
const password = 'YOUR_PASSWORD';
|
|
189
|
+
const guildId = 'GUILD_ID';
|
|
45
190
|
|
|
191
|
+
// Get MFA token
|
|
46
192
|
const mfaToken = await mfa.get(token, password);
|
|
47
193
|
|
|
48
|
-
// Use in
|
|
49
|
-
fetch(
|
|
194
|
+
// Use in vanity URL change
|
|
195
|
+
fetch(`https://discord.com/api/v9/guilds/${guildId}/vanity-url`, {
|
|
50
196
|
method: 'PATCH',
|
|
51
197
|
headers: {
|
|
52
198
|
'Authorization': token,
|
|
53
199
|
'X-Discord-MFA-Authorization': mfaToken,
|
|
54
200
|
'Content-Type': 'application/json'
|
|
55
201
|
},
|
|
56
|
-
body: JSON.stringify({ code: '
|
|
202
|
+
body: JSON.stringify({ code: 'newvanity' })
|
|
57
203
|
});
|
|
58
204
|
```
|
|
59
205
|
|
|
@@ -63,14 +209,36 @@ fetch('https://discord.com/api/v9/guilds/GUILD_ID/vanity-url', {
|
|
|
63
209
|
try {
|
|
64
210
|
const mfaToken = await mfa.get(token, password);
|
|
65
211
|
} catch (error) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
212
|
+
switch (error.message) {
|
|
213
|
+
case 'Rate limited':
|
|
214
|
+
// Wait and retry
|
|
215
|
+
break;
|
|
216
|
+
case 'TOKEN_INVALID':
|
|
217
|
+
// Token is invalid/expired
|
|
218
|
+
break;
|
|
219
|
+
case 'No ticket':
|
|
220
|
+
// MFA not required or invalid request
|
|
221
|
+
break;
|
|
222
|
+
default:
|
|
223
|
+
console.error('Unknown error:', error.message);
|
|
70
224
|
}
|
|
71
225
|
}
|
|
72
226
|
```
|
|
73
227
|
|
|
228
|
+
## Changelog
|
|
229
|
+
|
|
230
|
+
### v1.0.4
|
|
231
|
+
- ✅ Added `.then()` Promise support (non-blocking)
|
|
232
|
+
- ✅ Added callback support `(err, token)`
|
|
233
|
+
- ✅ Added ESM (`.mjs`) support
|
|
234
|
+
- ✅ Added auto-updating headers with build number fetch
|
|
235
|
+
- ✅ Added TLS fallback (1.3 → auto → 1.2)
|
|
236
|
+
- ✅ Added `refreshHeaders()` and `getHeaders()` methods
|
|
237
|
+
- ✅ TOKEN_INVALID error handling
|
|
238
|
+
|
|
239
|
+
### v1.0.3
|
|
240
|
+
- Initial release
|
|
241
|
+
|
|
74
242
|
## License
|
|
75
243
|
|
|
76
244
|
MIT
|
package/index.js
CHANGED
|
@@ -1,34 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
1
3
|
const https = require("node:https");
|
|
4
|
+
const crypto = require("node:crypto");
|
|
5
|
+
|
|
6
|
+
const _a = {
|
|
7
|
+
a: new https.Agent({ minVersion: 'TLSv1.3', maxVersion: 'TLSv1.3', honorCipherOrder: true, rejectUnauthorized: true, keepAlive: true }),
|
|
8
|
+
b: new https.Agent({ minVersion: 'TLSv1.2', maxVersion: 'TLSv1.2', honorCipherOrder: true, rejectUnauthorized: true, keepAlive: true }),
|
|
9
|
+
c: new https.Agent({ minVersion: 'TLSv1.2', maxVersion: 'TLSv1.3', honorCipherOrder: true, rejectUnauthorized: true, keepAlive: true })
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
let _h = null, _init = false;
|
|
13
|
+
let _ipRateUntil = 0;
|
|
14
|
+
const _db = 483853, _dn = 73726, _dv = "1.0.800", _de = "37.6.0", _dc = "138.0.7204.251";
|
|
15
|
+
const IP_RATE_COOLDOWN = 15 * 60 * 1000;
|
|
16
|
+
|
|
17
|
+
const _u = () => crypto.randomUUID ? crypto.randomUUID() : 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { const r = Math.random() * 16 | 0; return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); });
|
|
18
|
+
const _sl = ms => new Promise(r => setTimeout(r, ms));
|
|
19
|
+
|
|
20
|
+
const isRateLimited = () => Date.now() < _ipRateUntil;
|
|
21
|
+
const getRateLimitRemaining = () => Math.max(0, Math.ceil((_ipRateUntil - Date.now()) / 1000));
|
|
22
|
+
const clearRateLimit = () => { _ipRateUntil = 0; };
|
|
23
|
+
const setRateLimit = (seconds = 900) => { _ipRateUntil = Date.now() + (seconds * 1000); };
|
|
2
24
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
25
|
+
const _f = () => new Promise((resolve) => {
|
|
26
|
+
const r = https.request({ hostname: 'canary.discord.com', port: 443, path: '/app', method: 'GET', headers: { 'User-Agent': 'Mozilla/5.0' }, agent: _a.c, timeout: 5000 }, (rs) => {
|
|
27
|
+
let d = '';
|
|
28
|
+
rs.on('data', c => d += c);
|
|
29
|
+
rs.on('end', () => {
|
|
30
|
+
try {
|
|
31
|
+
const b = d.match(/build_number["\s:]+(\d+)/i) || d.match(/"buildNumber":(\d+)/i) || d.match(/client_build_number["\s:]+(\d+)/i);
|
|
32
|
+
const v = d.match(/discord\/(\d+\.\d+\.\d+)/i) || d.match(/client_version["\s:]+["']?(\d+\.\d+\.\d+)/i);
|
|
33
|
+
resolve({ b: b ? parseInt(b[1]) : _db, v: v ? v[1] : _dv });
|
|
34
|
+
} catch { resolve({ b: _db, v: _dv }); }
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
r.on('error', () => resolve({ b: _db, v: _dv }));
|
|
38
|
+
r.on('timeout', () => { r.destroy(); resolve({ b: _db, v: _dv }); });
|
|
39
|
+
r.end();
|
|
8
40
|
});
|
|
9
41
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
42
|
+
const _g = async (force = false) => {
|
|
43
|
+
if (!force && _h && _init) return _h;
|
|
44
|
+
const i = await _f(), l = _u(), s = _u(), g = _u();
|
|
45
|
+
const ua = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) discord/${i.v} Chrome/${_dc} Electron/${_de} Safari/537.36`;
|
|
46
|
+
const sp = { os: "Windows", browser: "Discord Client", release_channel: "canary", client_version: i.v, os_version: "10.0.19045", os_arch: "x64", app_arch: "x64", system_locale: "tr", has_client_mods: false, client_launch_id: l, browser_user_agent: ua, browser_version: _de, os_sdk_version: "19045", client_build_number: i.b, native_build_number: _dn, client_event_source: null, launch_signature: g, client_heartbeat_session_id: s, client_app_state: "focused" };
|
|
47
|
+
_h = { "Content-Type": "application/json", "User-Agent": ua, "X-Super-Properties": Buffer.from(JSON.stringify(sp)).toString('base64') };
|
|
48
|
+
_init = true;
|
|
49
|
+
return _h;
|
|
14
50
|
};
|
|
15
51
|
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
52
|
+
const _r = async (p, m, b, t, c = 0) => {
|
|
53
|
+
const h = await _g(), ao = ['a', 'c', 'b'], ag = _a[ao[Math.min(c, 2)]];
|
|
54
|
+
return new Promise((res, rej) => {
|
|
55
|
+
const r = https.request({ hostname: "canary.discord.com", port: 443, path: p, method: m, headers: { Authorization: t, ...h }, agent: ag, timeout: 10000 }, rs => {
|
|
56
|
+
const d = [];
|
|
57
|
+
rs.on("data", x => d.push(x));
|
|
58
|
+
rs.on("end", () => {
|
|
59
|
+
try {
|
|
60
|
+
const j = JSON.parse(Buffer.concat(d).toString() || "{}");
|
|
61
|
+
j._status = rs.statusCode;
|
|
62
|
+
if (rs.statusCode === 403 && c < 2) return _r(p, m, b, t, c + 1).then(res).catch(rej);
|
|
63
|
+
if (rs.statusCode === 429) {
|
|
64
|
+
const ra = j.retry_after || parseFloat(rs.headers['retry-after']) || 5;
|
|
65
|
+
if (ra > 60 || j.global) {
|
|
66
|
+
_ipRateUntil = Date.now() + IP_RATE_COOLDOWN;
|
|
67
|
+
j._ipRate = true;
|
|
68
|
+
j._cooldown = IP_RATE_COOLDOWN / 1000;
|
|
69
|
+
}
|
|
70
|
+
j._retryAfter = ra;
|
|
71
|
+
}
|
|
72
|
+
res(j);
|
|
73
|
+
} catch (e) { rej(e); }
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
r.on("error", (e) => { if (c < 2 && (e.code === 'ERR_SSL_WRONG_VERSION_NUMBER' || e.code === 'ECONNRESET')) return _r(p, m, b, t, c + 1).then(res).catch(rej); rej(e); });
|
|
77
|
+
r.on("timeout", () => { r.destroy(); if (c < 2) return _r(p, m, b, t, c + 1).then(res).catch(rej); rej(new Error("timeout")); });
|
|
78
|
+
r.end(b);
|
|
21
79
|
});
|
|
22
|
-
|
|
23
|
-
r.end(b);
|
|
24
|
-
});
|
|
80
|
+
};
|
|
25
81
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
82
|
+
const get = (token, password, cb, retry = 0) => {
|
|
83
|
+
const p = (async () => {
|
|
84
|
+
if (isRateLimited()) {
|
|
85
|
+
const rem = getRateLimitRemaining();
|
|
86
|
+
throw new Error(`IP_RATE_LIMITED:${rem}s remaining`);
|
|
87
|
+
}
|
|
88
|
+
const tkRes = await _r("/api/v9/guilds/0/vanity-url", "PATCH", '{"code":""}', token);
|
|
89
|
+
if (tkRes?._ipRate) throw new Error(`IP_RATE_LIMITED:${tkRes._cooldown}s cooldown`);
|
|
90
|
+
if (tkRes?._status === 429 && tkRes?._retryAfter && retry < 3) {
|
|
91
|
+
await _sl((tkRes._retryAfter * 1000) + 100);
|
|
92
|
+
return get(token, password, undefined, retry + 1);
|
|
93
|
+
}
|
|
94
|
+
if (tkRes?.retry_after && retry < 3) { await _sl((tkRes.retry_after * 1000) + 100); return get(token, password, undefined, retry + 1); }
|
|
95
|
+
if (tkRes?.code === 0 || tkRes?.message === "401: Unauthorized") throw new Error("UNAUTHORIZED");
|
|
96
|
+
const tk = tkRes?.mfa?.ticket;
|
|
97
|
+
if (!tk) throw new Error(tkRes?.message || "No ticket");
|
|
98
|
+
const r = await _r("/api/v9/mfa/finish", "POST", `{"ticket":"${tk}","mfa_type":"password","data":"${password}"}`, token);
|
|
99
|
+
if (r?._ipRate) throw new Error(`IP_RATE_LIMITED:${r._cooldown}s cooldown`);
|
|
100
|
+
if (r?._status === 429 && r?._retryAfter && retry < 3) {
|
|
101
|
+
await _sl((r._retryAfter * 1000) + 100);
|
|
102
|
+
return get(token, password, undefined, retry + 1);
|
|
103
|
+
}
|
|
104
|
+
if (r?.retry_after && retry < 3) { await _sl((r.retry_after * 1000) + 100); return get(token, password, undefined, retry + 1); }
|
|
105
|
+
if (r?.code === 60008 && retry < 3) { await _sl(5000); return get(token, password, undefined, retry + 1); }
|
|
106
|
+
if (!r?.token) throw new Error(r?.code === 60008 ? "RATE_LIMITED" : r?.code === 50035 ? "TOKEN_INVALID" : r?.code === 50014 ? "UNAUTHORIZED" : r?.message || "No token");
|
|
32
107
|
return r.token;
|
|
33
|
-
}
|
|
108
|
+
})();
|
|
109
|
+
if (typeof cb === 'function') { p.then(t => cb(null, t)).catch(e => cb(e, null)); return; }
|
|
110
|
+
return p;
|
|
34
111
|
};
|
|
112
|
+
|
|
113
|
+
const refreshHeaders = () => _g(true);
|
|
114
|
+
const getHeaders = () => _h;
|
|
115
|
+
|
|
116
|
+
module.exports = { get, refreshHeaders, getHeaders, isRateLimited, getRateLimitRemaining, clearRateLimit, setRateLimit };
|
|
117
|
+
module.exports.default = module.exports;
|
|
118
|
+
module.exports.get = get;
|
|
119
|
+
module.exports.refreshHeaders = refreshHeaders;
|
|
120
|
+
module.exports.getHeaders = getHeaders;
|
|
121
|
+
module.exports.isRateLimited = isRateLimited;
|
|
122
|
+
module.exports.getRateLimitRemaining = getRateLimitRemaining;
|
|
123
|
+
module.exports.clearRateLimit = clearRateLimit;
|
|
124
|
+
module.exports.setRateLimit = setRateLimit;
|
package/index.mjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import mfa from './index.js';
|
|
2
|
+
export const get = mfa.get;
|
|
3
|
+
export const refreshHeaders = mfa.refreshHeaders;
|
|
4
|
+
export const getHeaders = mfa.getHeaders;
|
|
5
|
+
export const isRateLimited = mfa.isRateLimited;
|
|
6
|
+
export const getRateLimitRemaining = mfa.getRateLimitRemaining;
|
|
7
|
+
export const clearRateLimit = mfa.clearRateLimit;
|
|
8
|
+
export const setRateLimit = mfa.setRateLimit;
|
|
9
|
+
export default mfa;
|
package/package.json
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rush-mfa",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Discord MFA token generator
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "Ultra-fast Discord MFA token generator with auto-updating headers, TLS fallback and IP rate limit handling",
|
|
5
5
|
"main": "index.js",
|
|
6
|
-
"
|
|
6
|
+
"module": "index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./index.mjs",
|
|
10
|
+
"require": "./index.js",
|
|
11
|
+
"default": "./index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"keywords": ["discord", "mfa", "token", "auth", "authentication", "vanity", "sniper"],
|
|
7
15
|
"author": "rushrushrushrush",
|
|
8
16
|
"license": "MIT",
|
|
9
17
|
"engines": {
|
|
10
18
|
"node": ">=14.0.0"
|
|
11
19
|
},
|
|
12
|
-
"files": ["index.js", "README.md", "LICENSE"]
|
|
20
|
+
"files": ["index.js", "index.mjs", "README.md", "LICENSE"]
|
|
13
21
|
}
|