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.
@@ -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
- try {
275
- const res = await fetch(`${API_URL}/api/grinder/config`, {
276
- headers: { Authorization: `Bearer ${API_KEY}` },
277
- });
278
- const data = await res.json();
279
- if (data.error) { log('error', `Config fetch failed: ${data.error}`); return null; }
280
- return data;
281
- } catch (err) { log('error', `Cannot reach API: ${err.message}`); return null; }
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
- const data = await fetchConfig();
1430
- if (!data) {
1446
+ let data = await fetchConfig(4, 2000);
1447
+ while (!data) {
1431
1448
  log('error', `Cannot connect to API`);
1432
- log('error', `Check your API key or API URL and try again.`);
1433
- process.exit(1);
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
- process.exit(1);
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.0",
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": "^3.6.1",
24
+ "discord.js-selfbot-v13": "3.5.0",
25
25
  "ioredis": "^5.10.1",
26
26
  "sharp": "^0.34.5"
27
27
  },