dankgrinder 5.0.4 → 5.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.
@@ -224,7 +224,6 @@ async function runInventory({ channel, waitForDankMemer, client, accountId, redi
224
224
  while (page < total) {
225
225
  const buttons = getAllButtons(response);
226
226
  const enabled = buttons.filter(b => !b.disabled);
227
- const expectedNextPage = page; // page is 1-based, paginator target indexes are usually 0-based
228
227
 
229
228
  const parseTargetPage = (customId) => {
230
229
  if (!customId) return null;
@@ -236,7 +235,7 @@ async function runInventory({ channel, waitForDankMemer, client, accountId, redi
236
235
  const id = String(b.customId || '');
237
236
  if (!/paginator-inventory-list/i.test(id)) return false;
238
237
  if (!/setpage/i.test(id)) return false;
239
- return parseTargetPage(id) === expectedNextPage;
238
+ return parseTargetPage(id) === page;
240
239
  });
241
240
 
242
241
  if (!nextBtn) {
@@ -244,7 +243,6 @@ async function runInventory({ channel, waitForDankMemer, client, accountId, redi
244
243
  const id = (b.customId || '').toLowerCase();
245
244
  const label = (b.label || '').toLowerCase();
246
245
  const emoji = (b.emoji?.name || '').toLowerCase();
247
- // Exclude backward/first/last page buttons
248
246
  if (id.includes('prev') || id.includes('first') || id.includes('last') || id.includes('back')) return false;
249
247
  if (label.includes('prev') || label.includes('back') || label === '◀' || label === '⏮' || label === '←' || label === '⏭') return false;
250
248
  if (emoji.includes('arrowleft') || emoji.includes('doubleleft') || emoji.includes('doubleright')) return false;
@@ -254,36 +252,62 @@ async function runInventory({ channel, waitForDankMemer, client, accountId, redi
254
252
  });
255
253
  }
256
254
 
257
- if (!nextBtn) {
258
- LOG.debug(`[inv] No next button on page ${page}`);
259
- break;
260
- }
255
+ if (!nextBtn) break;
256
+
257
+ await humanDelay(200, 400);
258
+
259
+ // Set up messageUpdate listener BEFORE clicking so we don't miss the update
260
+ const msgId = response.id;
261
+ const updatePromise = new Promise((resolve) => {
262
+ const timeout = setTimeout(() => {
263
+ client.removeListener('messageUpdate', handler);
264
+ resolve(null);
265
+ }, 10000);
266
+ const handler = (_, m) => {
267
+ if (m.id === msgId) {
268
+ clearTimeout(timeout);
269
+ client.removeListener('messageUpdate', handler);
270
+ resolve(m);
271
+ }
272
+ };
273
+ client.on('messageUpdate', handler);
274
+ });
261
275
 
262
- await humanDelay(150, 350);
263
276
  try {
264
- const result = await safeClickButton(response, nextBtn);
265
- if (result) {
266
- response = result;
267
- } else {
268
- await sleep(1200);
269
- }
270
- } catch (e) {
271
- LOG.error(`[inv] Next page click failed: ${e.message}`);
277
+ await safeClickButton(response, nextBtn);
278
+ } catch {
272
279
  break;
273
280
  }
274
281
 
275
- // Clear cached CV2 data so ensureCV2 re-fetches the updated message
282
+ // Wait for actual message update from Discord (page content change)
283
+ const updated = await updatePromise;
284
+ if (updated) {
285
+ response = updated;
286
+ }
287
+
288
+ // Force-refetch CV2 with retries until page actually changes
276
289
  delete response._cv2;
277
290
  delete response._cv2text;
278
291
  delete response._cv2buttons;
279
- await sleep(300);
280
- if (isCV2(response)) await ensureCV2(response);
281
- const pageInfo = parsePageInfo(response);
282
- if (pageInfo.page <= page) break;
283
- page = pageInfo.page;
284
- total = pageInfo.total;
285
-
286
- LOG.info(`[inv] Page ${page}/${total}`);
292
+
293
+ let pageChanged = false;
294
+ for (let attempt = 0; attempt < 4; attempt++) {
295
+ await sleep(attempt === 0 ? 600 : 1200);
296
+ if (isCV2(response)) await ensureCV2(response, true);
297
+ const pageInfo = parsePageInfo(response);
298
+ if (pageInfo.page > page) {
299
+ page = pageInfo.page;
300
+ total = pageInfo.total;
301
+ pageChanged = true;
302
+ break;
303
+ }
304
+ // Clear CV2 cache again for next retry
305
+ delete response._cv2;
306
+ delete response._cv2text;
307
+ delete response._cv2buttons;
308
+ }
309
+
310
+ if (!pageChanged) break;
287
311
  allItems.push(...parseInventoryPage(response));
288
312
  }
289
313
 
@@ -388,7 +412,7 @@ async function getAllInventories(redis, accountIds) {
388
412
  }
389
413
 
390
414
  module.exports = {
391
- runInventory, fetchItemValues, enrichItems,
415
+ runInventory, fetchItemValues, enrichItems, parsePageInfo,
392
416
  getCachedInventory, getAllInventories,
393
417
  updateInventoryItem, deleteInventoryItem,
394
418
  binarySearchItem, itemNameTrie, itemValueCache,
@@ -59,11 +59,7 @@ const c = {
59
59
  let _dashboardActive = false;
60
60
  function setDashboardActive(val) { _dashboardActive = val; }
61
61
 
62
- function log(label, msg) {
63
- if (_dashboardActive) return;
64
- const time = new Date().toLocaleTimeString('en-US', { hour12: true, hour: '2-digit', minute: '2-digit', second: '2-digit' });
65
- console.log(` ${c.dim}${time}${c.reset} ${label} ${msg}`);
66
- }
62
+ function log() {}
67
63
 
68
64
  const LOG = {
69
65
  info: (msg) => log(`${c.cyan}│${c.reset}`, msg),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dankgrinder",
3
- "version": "5.0.4",
3
+ "version": "5.0.6",
4
4
  "description": "Dank Memer automation engine — grind coins while you sleep",
5
5
  "bin": {
6
6
  "dankgrinder": "bin/dankgrinder.js"