dankgrinder 4.8.0 → 4.8.1
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/bin/dankgrinder.js +18 -0
- package/lib/grinder.js +33 -15
- package/package.json +2 -2
package/bin/dankgrinder.js
CHANGED
|
@@ -46,6 +46,24 @@ for (let i = 0; i < args.length; i++) {
|
|
|
46
46
|
apiUrl = apiUrl || process.env.DANKGRINDER_URL || DEFAULT_URL;
|
|
47
47
|
if (redisUrl) process.env.REDIS_URL = redisUrl;
|
|
48
48
|
|
|
49
|
+
// Keep process alive on transient discord interaction fetch failures.
|
|
50
|
+
process.on('uncaughtException', (err) => {
|
|
51
|
+
const msg = String(err?.message || err || '');
|
|
52
|
+
const stack = String(err?.stack || '');
|
|
53
|
+
if (msg.toLowerCase().includes('fetch failed') && stack.includes('discord.js-selfbot-v13')) {
|
|
54
|
+
console.error(`\n ${C.red}✗ Discord interaction fetch failed (transient). Continuing...${C.r}\n`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
throw err;
|
|
58
|
+
});
|
|
59
|
+
process.on('unhandledRejection', (reason) => {
|
|
60
|
+
const msg = String(reason?.message || reason || '');
|
|
61
|
+
if (msg.toLowerCase().includes('fetch failed')) {
|
|
62
|
+
console.error(`\n ${C.red}✗ Unhandled fetch failure (network/transient). Continuing...${C.r}\n`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
49
67
|
if (!apiKey) {
|
|
50
68
|
console.error(`\n ${C.red}✗ Missing API key.${C.r}\n`);
|
|
51
69
|
console.error(` ${C.b}Usage:${C.r} npx dankgrinder --key <YOUR_API_KEY>\n`);
|
package/lib/grinder.js
CHANGED
|
@@ -270,15 +270,32 @@ function log(type, msg, label) {
|
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
async function fetchConfig() {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
273
|
+
async function fetchConfig(retries = 3, delayMs = 1500) {
|
|
274
|
+
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
275
|
+
try {
|
|
276
|
+
const controller = new AbortController();
|
|
277
|
+
const t = setTimeout(() => controller.abort(), 10000);
|
|
278
|
+
const res = await fetch(`${API_URL}/api/grinder/config`, {
|
|
279
|
+
headers: { Authorization: `Bearer ${API_KEY}` },
|
|
280
|
+
signal: controller.signal,
|
|
281
|
+
});
|
|
282
|
+
clearTimeout(t);
|
|
283
|
+
const data = await res.json();
|
|
284
|
+
if (data.error) {
|
|
285
|
+
log('error', `Config fetch failed: ${data.error}`);
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
return data;
|
|
289
|
+
} catch (err) {
|
|
290
|
+
if (attempt < retries) {
|
|
291
|
+
log('warn', `API fetch failed (attempt ${attempt}/${retries}) — retrying...`);
|
|
292
|
+
await new Promise((r) => setTimeout(r, delayMs * attempt));
|
|
293
|
+
} else {
|
|
294
|
+
log('error', `Cannot reach API: ${err.message}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return null;
|
|
282
299
|
}
|
|
283
300
|
|
|
284
301
|
async function sendLog(accountName, command, response, status) {
|
|
@@ -1411,7 +1428,7 @@ async function start(apiKey, apiUrl) {
|
|
|
1411
1428
|
|
|
1412
1429
|
console.log(colorBanner());
|
|
1413
1430
|
console.log(
|
|
1414
|
-
` ${rgb(139, 92, 246)}v4.8${c.reset}` +
|
|
1431
|
+
` ${rgb(139, 92, 246)}v4.8.1${c.reset}` +
|
|
1415
1432
|
` ${c.dim}·${c.reset} ${c.white}30 Commands${c.reset}` +
|
|
1416
1433
|
` ${c.dim}·${c.reset} ${rgb(34, 211, 238)}Priority Queue${c.reset}` +
|
|
1417
1434
|
` ${c.dim}·${c.reset} ${rgb(52, 211, 153)}Redis Cooldowns${c.reset}` +
|
|
@@ -1426,17 +1443,18 @@ async function start(apiKey, apiUrl) {
|
|
|
1426
1443
|
|
|
1427
1444
|
log('info', `${c.dim}Fetching accounts...${c.reset}`);
|
|
1428
1445
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1446
|
+
let data = await fetchConfig(4, 2000);
|
|
1447
|
+
while (!data) {
|
|
1431
1448
|
log('error', `Cannot connect to API`);
|
|
1432
|
-
log('
|
|
1433
|
-
|
|
1449
|
+
log('warn', `Will retry in 10s (check internet/API URL if this repeats).`);
|
|
1450
|
+
await new Promise((r) => setTimeout(r, 10000));
|
|
1451
|
+
data = await fetchConfig(4, 2000);
|
|
1434
1452
|
}
|
|
1435
1453
|
|
|
1436
1454
|
const { accounts } = data;
|
|
1437
1455
|
if (!accounts || accounts.length === 0) {
|
|
1438
1456
|
log('error', 'No active accounts. Add them in the dashboard.');
|
|
1439
|
-
|
|
1457
|
+
return;
|
|
1440
1458
|
}
|
|
1441
1459
|
|
|
1442
1460
|
checks.push(`${rgb(52, 211, 153)}✓${c.reset} ${c.white}${accounts.length} Account${accounts.length > 1 ? 's' : ''}${c.reset}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dankgrinder",
|
|
3
|
-
"version": "4.8.
|
|
3
|
+
"version": "4.8.1",
|
|
4
4
|
"description": "Dank Memer automation engine — grind coins while you sleep",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dankgrinder": "bin/dankgrinder.js"
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"debug": "^4.4.0",
|
|
24
|
-
"discord.js-selfbot-v13": "
|
|
24
|
+
"discord.js-selfbot-v13": "3.5.0",
|
|
25
25
|
"ioredis": "^5.10.1",
|
|
26
26
|
"sharp": "^0.34.5"
|
|
27
27
|
},
|