wsnipz 1.2.4 → 1.2.5
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/checker.js +13 -6
- package/dist/discord.js +16 -11
- package/dist/generators.js +27 -6
- package/dist/prompts.js +13 -13
- package/dist/proxies.js +23 -3
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/checker.js
CHANGED
|
@@ -5,7 +5,7 @@ const discord_1 = require("./discord");
|
|
|
5
5
|
function sleep(ms) {
|
|
6
6
|
return new Promise((r) => setTimeout(r, ms));
|
|
7
7
|
}
|
|
8
|
-
const MAX_RETRIES =
|
|
8
|
+
const MAX_RETRIES = 8;
|
|
9
9
|
async function checkUsernames(usernames, opts) {
|
|
10
10
|
const results = [];
|
|
11
11
|
let cursor = 0;
|
|
@@ -23,12 +23,19 @@ async function checkUsernames(usernames, opts) {
|
|
|
23
23
|
const username = usernames[i];
|
|
24
24
|
let res = await (0, discord_1.checkUsername)(username, opts.token, opts.pool);
|
|
25
25
|
let attempt = 0;
|
|
26
|
-
while (res.status === 'ratelimited'
|
|
26
|
+
while ((res.status === 'ratelimited' ||
|
|
27
|
+
(res.status === 'error' && res.retryable)) &&
|
|
28
|
+
attempt < MAX_RETRIES) {
|
|
27
29
|
attempt++;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if (res.status === 'ratelimited') {
|
|
31
|
+
const retryAfter = res.retryAfter ?? 1;
|
|
32
|
+
const waitMs = Math.min(Math.max(retryAfter * 1000, 1000) * Math.pow(2, attempt - 1), 30000);
|
|
33
|
+
globalRateLimitUntil = Math.max(globalRateLimitUntil, Date.now() + waitMs);
|
|
34
|
+
await sleep(waitMs);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
await sleep(500 * attempt);
|
|
38
|
+
}
|
|
32
39
|
res = await (0, discord_1.checkUsername)(username, opts.token, opts.pool);
|
|
33
40
|
}
|
|
34
41
|
const result = {
|
package/dist/discord.js
CHANGED
|
@@ -20,7 +20,7 @@ async function checkUsername(username, token, pool) {
|
|
|
20
20
|
headers: { ...DEFAULT_HEADERS, Authorization: token },
|
|
21
21
|
data: { username },
|
|
22
22
|
validateStatus: () => true,
|
|
23
|
-
timeout:
|
|
23
|
+
timeout: 10000,
|
|
24
24
|
proxy: false,
|
|
25
25
|
};
|
|
26
26
|
const proxyUrl = pool?.next() ?? undefined;
|
|
@@ -31,37 +31,42 @@ async function checkUsername(username, token, pool) {
|
|
|
31
31
|
}
|
|
32
32
|
try {
|
|
33
33
|
const res = await axios_1.default.request(config);
|
|
34
|
+
if (proxyUrl)
|
|
35
|
+
pool?.markSuccess(proxyUrl);
|
|
34
36
|
if (res.status === 204 || res.status === 200) {
|
|
35
37
|
if (res.data?.taken === true) {
|
|
36
|
-
return { status: 'taken', message: 'Username already taken' };
|
|
38
|
+
return { status: 'taken', message: 'Username already taken', proxyUsed: proxyUrl };
|
|
37
39
|
}
|
|
38
|
-
return { status: 'available' };
|
|
40
|
+
return { status: 'available', proxyUsed: proxyUrl };
|
|
39
41
|
}
|
|
40
42
|
if (res.status === 429) {
|
|
41
43
|
const retryAfter = Number(res.data?.retry_after ?? 1);
|
|
42
|
-
return { status: 'ratelimited', retryAfter: isNaN(retryAfter) ? 1 : retryAfter };
|
|
44
|
+
return { status: 'ratelimited', retryAfter: isNaN(retryAfter) ? 1 : retryAfter, proxyUsed: proxyUrl };
|
|
43
45
|
}
|
|
44
46
|
if (res.status === 400) {
|
|
45
47
|
if (res.data?.taken === true) {
|
|
46
|
-
return { status: 'taken', message: 'Username already taken' };
|
|
48
|
+
return { status: 'taken', message: 'Username already taken', proxyUsed: proxyUrl };
|
|
47
49
|
}
|
|
48
50
|
const usernameErrors = res.data?.errors?.username?._errors || [];
|
|
49
51
|
const codes = usernameErrors.map((e) => e.code).filter(Boolean);
|
|
50
52
|
if (codes.includes('USERNAME_TOO_MANY_RESULTS')) {
|
|
51
|
-
return { status: 'taken', message: 'Username already taken' };
|
|
53
|
+
return { status: 'taken', message: 'Username already taken', proxyUsed: proxyUrl };
|
|
52
54
|
}
|
|
53
55
|
if (codes.length > 0) {
|
|
54
|
-
return { status: 'invalid', message: codes.join(', ') };
|
|
56
|
+
return { status: 'invalid', message: codes.join(', '), proxyUsed: proxyUrl };
|
|
55
57
|
}
|
|
56
|
-
return { status: 'invalid', message: 'Invalid format' };
|
|
58
|
+
return { status: 'invalid', message: 'Invalid format', proxyUsed: proxyUrl };
|
|
57
59
|
}
|
|
58
60
|
if (res.status === 401 || res.status === 403) {
|
|
59
|
-
return { status: 'error', message: `Invalid token (${res.status})
|
|
61
|
+
return { status: 'error', message: `Invalid token (${res.status})`, proxyUsed: proxyUrl };
|
|
60
62
|
}
|
|
61
|
-
return { status: 'error', message: `HTTP ${res.status}
|
|
63
|
+
return { status: 'error', message: `HTTP ${res.status}`, proxyUsed: proxyUrl };
|
|
62
64
|
}
|
|
63
65
|
catch (err) {
|
|
64
|
-
|
|
66
|
+
if (proxyUrl)
|
|
67
|
+
pool?.markFailed(proxyUrl);
|
|
68
|
+
const code = err?.code || err?.message || 'Network error';
|
|
69
|
+
return { status: 'error', message: code, retryable: true, proxyUsed: proxyUrl };
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
async function validateToken(token, pool) {
|
package/dist/generators.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.charsetFor = charsetFor;
|
|
|
5
5
|
exports.patternLabel = patternLabel;
|
|
6
6
|
exports.generateUsernames = generateUsernames;
|
|
7
7
|
exports.maxUniqueFor = maxUniqueFor;
|
|
8
|
+
exports.generateAllCombinations = generateAllCombinations;
|
|
8
9
|
exports.LETTERS = 'abcdefghijklmnopqrstuvwxyz';
|
|
9
10
|
exports.DIGITS = '0123456789';
|
|
10
11
|
exports.SPECIAL = '._';
|
|
@@ -17,12 +18,12 @@ const PATTERN_SETS = {
|
|
|
17
18
|
'digits+special': exports.DIGITS + exports.SPECIAL,
|
|
18
19
|
};
|
|
19
20
|
const PATTERN_LABELS = {
|
|
20
|
-
'letters': '
|
|
21
|
-
'digits': '
|
|
22
|
-
'letters+digits': '
|
|
23
|
-
'letters+special': '
|
|
24
|
-
'letters+digits+special': '
|
|
25
|
-
'digits+special': '
|
|
21
|
+
'letters': 'Letters (a-z)',
|
|
22
|
+
'digits': 'Digits (0-9)',
|
|
23
|
+
'letters+digits': 'Letters + Digits',
|
|
24
|
+
'letters+special': 'Letters + Special characters (._)',
|
|
25
|
+
'letters+digits+special': 'Letters + Digits + Special characters',
|
|
26
|
+
'digits+special': 'Digits + Special characters',
|
|
26
27
|
};
|
|
27
28
|
function charsetFor(pattern) {
|
|
28
29
|
return PATTERN_SETS[pattern];
|
|
@@ -57,3 +58,23 @@ function maxUniqueFor(pattern, length) {
|
|
|
57
58
|
const charset = charsetFor(pattern);
|
|
58
59
|
return Math.pow(charset.length, length);
|
|
59
60
|
}
|
|
61
|
+
function generateAllCombinations(pattern, length) {
|
|
62
|
+
const charset = charsetFor(pattern);
|
|
63
|
+
const out = [];
|
|
64
|
+
const indices = new Array(length).fill(0);
|
|
65
|
+
const total = maxUniqueFor(pattern, length);
|
|
66
|
+
for (let n = 0; n < total; n++) {
|
|
67
|
+
let name = '';
|
|
68
|
+
for (let i = 0; i < length; i++) {
|
|
69
|
+
name += charset[indices[i]];
|
|
70
|
+
}
|
|
71
|
+
out.push(name);
|
|
72
|
+
for (let i = length - 1; i >= 0; i--) {
|
|
73
|
+
indices[i]++;
|
|
74
|
+
if (indices[i] < charset.length)
|
|
75
|
+
break;
|
|
76
|
+
indices[i] = 0;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
package/dist/prompts.js
CHANGED
|
@@ -179,17 +179,6 @@ async function runChecker(config, save) {
|
|
|
179
179
|
validate: (v) => v >= 2 && v <= maxLen ? true : `Between 2 and ${maxLen}`,
|
|
180
180
|
});
|
|
181
181
|
const maxUnique = (0, generators_1.maxUniqueFor)(pattern, length);
|
|
182
|
-
const { count } = await inquirer_1.default.prompt({
|
|
183
|
-
type: 'number',
|
|
184
|
-
name: 'count',
|
|
185
|
-
message: 'How many usernames to check?',
|
|
186
|
-
default: 50,
|
|
187
|
-
validate: (v) => v >= 1 && v <= 100000 ? true : 'Between 1 and 100000',
|
|
188
|
-
});
|
|
189
|
-
const effectiveCount = Math.min(count, maxUnique);
|
|
190
|
-
if (effectiveCount < count) {
|
|
191
|
-
console.log(chalk_1.default.yellow(` Only ${maxUnique} possible combinations for "${(0, generators_1.patternLabel)(pattern)}" of length ${length}.`));
|
|
192
|
-
}
|
|
193
182
|
const token = await ensureToken(config, save);
|
|
194
183
|
const pool = await ensureProxyPool(config);
|
|
195
184
|
save(config);
|
|
@@ -207,8 +196,12 @@ async function runChecker(config, save) {
|
|
|
207
196
|
default: pool && pool.size > 0 ? 200 : 800,
|
|
208
197
|
validate: (v) => v >= 0 ? true : '>= 0',
|
|
209
198
|
});
|
|
210
|
-
const
|
|
211
|
-
|
|
199
|
+
const comboSpinner = (0, ora_1.default)({ text: 'Creating the combolist...', spinner: 'dots' }).start();
|
|
200
|
+
const usernames = (0, generators_1.generateAllCombinations)(pattern, length);
|
|
201
|
+
const comboFile = `combolist_${Date.now()}.txt`;
|
|
202
|
+
fs_1.default.writeFileSync(comboFile, usernames.join('\n'), 'utf-8');
|
|
203
|
+
comboSpinner.succeed(chalk_1.default.green(`Combolist created: ${chalk_1.default.bold(comboFile)} `) +
|
|
204
|
+
chalk_1.default.gray(`(${usernames.length} combinations)`));
|
|
212
205
|
const stats = { available: 0, taken: 0, invalid: 0, errors: 0, total: usernames.length };
|
|
213
206
|
const spinner = (0, ora_1.default)({ text: 'Checking...', spinner: 'dots' }).start();
|
|
214
207
|
const purple = chalk_1.default.hex('#9B59B6').bold;
|
|
@@ -269,6 +262,13 @@ async function runChecker(config, save) {
|
|
|
269
262
|
const resFile = `results_${stamp}.txt`;
|
|
270
263
|
fs_1.default.writeFileSync(resFile, results.map((r) => `${r.username}\t${r.status}${r.message ? '\t' + r.message : ''}`).join('\n'), 'utf-8');
|
|
271
264
|
console.log(chalk_1.default.gray(` Full results: ${resFile}\n`));
|
|
265
|
+
try {
|
|
266
|
+
fs_1.default.unlinkSync(comboFile);
|
|
267
|
+
console.log(chalk_1.default.gray(` Combolist removed: ${comboFile}`));
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
// ignore deletion errors
|
|
271
|
+
}
|
|
272
272
|
}
|
|
273
273
|
async function configureSettings(config, save) {
|
|
274
274
|
console.log((0, ui_1.box)('Current configuration', [
|
package/dist/proxies.js
CHANGED
|
@@ -50,6 +50,8 @@ class ProxyPool {
|
|
|
50
50
|
constructor(proxies = [], rotating = false) {
|
|
51
51
|
this.proxies = [];
|
|
52
52
|
this.index = 0;
|
|
53
|
+
this.failures = new Map();
|
|
54
|
+
this.dead = new Set();
|
|
53
55
|
this.rotating = false;
|
|
54
56
|
this.proxies = proxies;
|
|
55
57
|
this.rotating = rotating;
|
|
@@ -57,6 +59,9 @@ class ProxyPool {
|
|
|
57
59
|
get size() {
|
|
58
60
|
return this.proxies.length;
|
|
59
61
|
}
|
|
62
|
+
get aliveCount() {
|
|
63
|
+
return this.proxies.length - this.dead.size;
|
|
64
|
+
}
|
|
60
65
|
get list() {
|
|
61
66
|
return [...this.proxies];
|
|
62
67
|
}
|
|
@@ -73,12 +78,27 @@ class ProxyPool {
|
|
|
73
78
|
next() {
|
|
74
79
|
if (this.proxies.length === 0)
|
|
75
80
|
return null;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
for (let attempt = 0; attempt < this.proxies.length; attempt++) {
|
|
82
|
+
const proxy = this.proxies[this.index % this.proxies.length];
|
|
83
|
+
this.index++;
|
|
84
|
+
if (!this.dead.has(proxy))
|
|
85
|
+
return proxy;
|
|
86
|
+
}
|
|
87
|
+
return this.proxies.length > 0 ? this.proxies[0] : null;
|
|
88
|
+
}
|
|
89
|
+
markFailed(proxyUrl) {
|
|
90
|
+
const count = (this.failures.get(proxyUrl) ?? 0) + 1;
|
|
91
|
+
this.failures.set(proxyUrl, count);
|
|
92
|
+
if (count >= ProxyPool.MAX_FAILURES) {
|
|
93
|
+
this.dead.add(proxyUrl);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
markSuccess(proxyUrl) {
|
|
97
|
+
this.failures.delete(proxyUrl);
|
|
79
98
|
}
|
|
80
99
|
createAgent(proxyUrl) {
|
|
81
100
|
return new ProxyAgent(proxyUrl);
|
|
82
101
|
}
|
|
83
102
|
}
|
|
84
103
|
exports.ProxyPool = ProxyPool;
|
|
104
|
+
ProxyPool.MAX_FAILURES = 3;
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name": "wsnipz", "version": "1.2.
|
|
1
|
+
{"name": "wsnipz", "version": "1.2.5", "description": "A modern Discord username availability checker CLI with rotating proxy support.", "main": "dist/index.js", "bin": {"wsniper": "dist/index.js", "wsnipz": "dist/index.js"}, "files": ["dist"], "scripts": {"build": "tsc", "dev": "ts-node src/index.ts", "start": "node dist/index.js", "prepublishOnly": "npm run build"}, "keywords": ["discord", "username", "checker", "sniper", "cli", "proxy", "availability", "wsnipz"], "author": "", "license": "MIT", "engines": {"node": ">=16"}, "dependencies": {"axios": "^1.7.7", "chalk": "^4.1.2", "cli-table3": "^0.6.5", "commander": "^11.1.0", "figlet": "^1.8.0", "inquirer": "^8.2.6", "ora": "^5.4.1", "proxy-agent": "^5.0.0"}, "devDependencies": {"@types/figlet": "^1.7.0", "@types/inquirer": "^8.2.10", "@types/node": "^20.16.0", "ts-node": "^10.9.2", "typescript": "^5.6.0"}}
|