dankgrinder 5.23.0 → 5.24.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.
@@ -233,6 +233,7 @@ async function runInventory({ channel, waitForDankMemer, client, accountId, redi
233
233
  allItems.push(...parseInventoryPage(response));
234
234
 
235
235
  let guard = 0;
236
+ let noChangeCount = 0;
236
237
  while (page < total && guard < Math.max(20, total + 6)) {
237
238
  guard++;
238
239
  const buttons = getAllButtons(response);
@@ -312,12 +313,17 @@ async function runInventory({ channel, waitForDankMemer, client, accountId, redi
312
313
  delete response._cv2buttons;
313
314
 
314
315
  let pageChanged = false;
315
- for (let attempt = 0; attempt < 4; attempt++) {
316
- await sleep(attempt === 0 ? 600 : 1200);
316
+ for (let attempt = 0; attempt < 7; attempt++) {
317
+ await sleep(attempt === 0 ? 700 : 1100 + Math.min(attempt * 150, 600));
317
318
  try {
318
- const fresh = await channel.messages.fetch(response.id);
319
+ const fresh = await response.fetch(true);
319
320
  if (fresh) response = fresh;
320
- } catch {}
321
+ } catch {
322
+ try {
323
+ const fresh = await channel.messages.fetch(response.id);
324
+ if (fresh) response = fresh;
325
+ } catch {}
326
+ }
321
327
  if (isCV2(response)) await ensureCV2(response, true);
322
328
  const pageInfo = parsePageInfo(response);
323
329
  if (pageInfo.page > page && !visitedPages.has(pageInfo.page)) {
@@ -337,7 +343,16 @@ async function runInventory({ channel, waitForDankMemer, client, accountId, redi
337
343
  delete response._cv2buttons;
338
344
  }
339
345
 
340
- if (!pageChanged) break;
346
+ if (!pageChanged) {
347
+ noChangeCount++;
348
+ if (noChangeCount < 3) {
349
+ LOG.warn(`[inv] Page stuck at ${page}/${total}; retrying paginator click (${noChangeCount}/2)`);
350
+ await sleep(900 + Math.floor(Math.random() * 500));
351
+ continue;
352
+ }
353
+ break;
354
+ }
355
+ noChangeCount = 0;
341
356
  allItems.push(...parseInventoryPage(response));
342
357
  }
343
358
 
package/lib/grinder.js CHANGED
@@ -1147,7 +1147,7 @@ class AccountWorker {
1147
1147
  lastErr = e;
1148
1148
  if (attempt < tries) {
1149
1149
  this.log('warn', `Inventory attempt ${attempt}/${tries} failed (${e.message}). Retrying...`);
1150
- await sleep(1500 + Math.floor(Math.random() * 1500));
1150
+ await new Promise((r) => setTimeout(r, 1500 + Math.floor(Math.random() * 1500)));
1151
1151
  continue;
1152
1152
  }
1153
1153
  }
@@ -2438,17 +2438,31 @@ async function start(apiKey, apiUrl) {
2438
2438
  console.log('');
2439
2439
 
2440
2440
  // Phase 1: Login all accounts (staggered to avoid 429s)
2441
- const BATCH_SIZE = 5;
2442
- const BATCH_DELAY_MS = 3000;
2441
+ const LOGIN_PROGRESS_EVERY = 5;
2442
+ const parsedGapMin = Number.parseInt(String(process.env.LOGIN_GAP_MIN_MS || '100'), 10);
2443
+ const parsedGapMax = Number.parseInt(String(process.env.LOGIN_GAP_MAX_MS || '300'), 10);
2444
+ const LOGIN_GAP_MIN_MS = Number.isFinite(parsedGapMin) && parsedGapMin >= 0 ? parsedGapMin : 100;
2445
+ const LOGIN_GAP_MAX_MS = Number.isFinite(parsedGapMax) && parsedGapMax >= LOGIN_GAP_MIN_MS ? parsedGapMax : Math.max(LOGIN_GAP_MIN_MS, 300);
2446
+
2447
+ const randomLoginGap = () => {
2448
+ if (LOGIN_GAP_MAX_MS <= LOGIN_GAP_MIN_MS) return LOGIN_GAP_MIN_MS;
2449
+ return LOGIN_GAP_MIN_MS + Math.floor(Math.random() * (LOGIN_GAP_MAX_MS - LOGIN_GAP_MIN_MS + 1));
2450
+ };
2451
+
2443
2452
  for (let i = 0; i < accounts.length; i++) {
2444
2453
  if (shutdownCalled) break;
2445
2454
  const worker = new AccountWorker(accounts[i], i);
2446
2455
  workers.push(worker);
2447
2456
  workerMap.set(accounts[i].id, worker);
2448
2457
  await worker.start();
2449
- if ((i + 1) % BATCH_SIZE === 0 && i + 1 < accounts.length) {
2450
- log('info', `${c.dim}Logged in ${i + 1}/${accounts.length}, next batch in ${BATCH_DELAY_MS / 1000}s...${c.reset}`);
2451
- await new Promise(r => setTimeout(r, BATCH_DELAY_MS));
2458
+ if (i + 1 < accounts.length) {
2459
+ const gapMs = randomLoginGap();
2460
+ if ((i + 1) % LOGIN_PROGRESS_EVERY === 0) {
2461
+ log('info', `${c.dim}Logged in ${i + 1}/${accounts.length}, next account in ${gapMs}ms...${c.reset}`);
2462
+ }
2463
+ await new Promise(r => setTimeout(r, gapMs));
2464
+ }
2465
+ if ((i + 1) % LOGIN_PROGRESS_EVERY === 0) {
2452
2466
  hintGC();
2453
2467
  }
2454
2468
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dankgrinder",
3
- "version": "5.23.0",
3
+ "version": "5.24.0",
4
4
  "description": "Dank Memer automation engine — grind coins while you sleep",
5
5
  "bin": {
6
6
  "dankgrinder": "bin/dankgrinder.js"