dankgrinder 4.3.0 → 4.3.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.
@@ -365,9 +365,12 @@ async function runAdventure({ channel, waitForDankMemer, client }) {
365
365
 
366
366
  // ── Select adventure type from dropdown ─────────────────────
367
367
  if (menus.length > 0) {
368
- // Re-fetch message to get hydrated components (minValues/maxValues)
369
- const freshMsg = await channel.messages.fetch(response.id).catch(() => null);
370
- if (freshMsg) response = freshMsg;
368
+ try {
369
+ if (channel.messages && typeof channel.messages.fetch === 'function') {
370
+ const freshMsg = await channel.messages.fetch(response.id);
371
+ if (freshMsg) response = freshMsg;
372
+ }
373
+ } catch { /* proceed with original */ }
371
374
 
372
375
  // Find the select menu row index
373
376
  let menuRowIdx = -1;
@@ -99,9 +99,12 @@ async function runGeneric({ channel, waitForDankMemer, cmdString, cmdName, clien
99
99
  // Handle select menus
100
100
  const menus = getAllSelectMenus(response);
101
101
  if (menus.length > 0) {
102
- // Re-fetch for hydrated components (minValues/maxValues)
103
- const freshMsg = await channel.messages.fetch(response.id).catch(() => null);
104
- if (freshMsg) response = freshMsg;
102
+ try {
103
+ if (channel.messages && typeof channel.messages.fetch === 'function') {
104
+ const freshMsg = await channel.messages.fetch(response.id);
105
+ if (freshMsg) response = freshMsg;
106
+ }
107
+ } catch { /* proceed with original */ }
105
108
  // Find row index of first select menu
106
109
  let menuRowIdx = -1;
107
110
  for (let i = 0; i < (response.components || []).length; i++) {
@@ -79,9 +79,13 @@ async function buyItem({ channel, waitForDankMemer, itemName, quantity = 1, clie
79
79
  }
80
80
 
81
81
  // Step 2: Navigate to Coin Shop tab
82
- // Re-fetch message to get hydrated components (minValues/maxValues for selectMenu)
83
- const freshShopMsg = await channel.messages.fetch(response.id).catch(() => null);
84
- if (freshShopMsg) response = freshShopMsg;
82
+ // Try re-fetch for hydrated components; skip if unavailable
83
+ try {
84
+ if (channel.messages && typeof channel.messages.fetch === 'function') {
85
+ const freshShopMsg = await channel.messages.fetch(response.id);
86
+ if (freshShopMsg) response = freshShopMsg;
87
+ }
88
+ } catch { /* proceed with original response */ }
85
89
 
86
90
  const csInfo = findSelectMenuOption(response, 'Coin Shop');
87
91
  if (csInfo) {
@@ -13,7 +13,13 @@ const c = {
13
13
  };
14
14
 
15
15
  // ── Logging ──────────────────────────────────────────────────
16
+ // When dashboard is active, suppress direct console output from command handlers.
17
+ // grinder.js sets this to true once the live dashboard starts rendering.
18
+ let _dashboardActive = false;
19
+ function setDashboardActive(val) { _dashboardActive = val; }
20
+
16
21
  function log(label, msg) {
22
+ if (_dashboardActive) return;
17
23
  const time = new Date().toLocaleTimeString('en-US', { hour12: true, hour: '2-digit', minute: '2-digit', second: '2-digit' });
18
24
  console.log(` ${c.dim}${time}${c.reset} ${label} ${msg}`);
19
25
  }
@@ -277,6 +283,7 @@ module.exports = {
277
283
  DANK_MEMER_ID,
278
284
  c,
279
285
  LOG,
286
+ setDashboardActive,
280
287
  sleep,
281
288
  humanDelay,
282
289
  getFullText,
package/lib/grinder.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const { Client } = require('discord.js-selfbot-v13');
2
2
  const Redis = require('ioredis');
3
3
  const commands = require('./commands');
4
+ const { setDashboardActive } = require('./commands/utils');
4
5
 
5
6
  // ── Terminal Colors & ANSI ───────────────────────────────────
6
7
  const c = {
@@ -948,6 +949,38 @@ class AccountWorker {
948
949
  return heap;
949
950
  }
950
951
 
952
+ // Merge config changes into existing queue without resetting cooldown timings.
953
+ // Uses a HashMap to drain old items, then rebuilds preserving nextRunAt.
954
+ mergeCommandQueue() {
955
+ const enabled = new Set(
956
+ AccountWorker.COMMAND_MAP.filter(ci => Boolean(this.account[ci.key])).map(ci => ci.cmd)
957
+ );
958
+ if (enabled.size === 0) return;
959
+
960
+ const existing = new Map();
961
+ if (this.commandQueue) {
962
+ while (this.commandQueue.size > 0) {
963
+ const item = this.commandQueue.pop();
964
+ existing.set(item.cmd, item);
965
+ }
966
+ }
967
+
968
+ const heap = new MinHeap();
969
+ const now = Date.now();
970
+ for (const info of AccountWorker.COMMAND_MAP) {
971
+ if (!enabled.has(info.cmd)) continue;
972
+ const old = existing.get(info.cmd);
973
+ if (old) {
974
+ old.info = info;
975
+ old.priority = info.priority;
976
+ heap.push(old);
977
+ } else {
978
+ heap.push({ cmd: info.cmd, nextRunAt: now, priority: info.priority, info });
979
+ }
980
+ }
981
+ this.commandQueue = heap;
982
+ }
983
+
951
984
  // ── Health Check: verify Discord client is still connected ──
952
985
  async healthCheck() {
953
986
  if (!this.running || shutdownCalled) return;
@@ -1117,7 +1150,7 @@ class AccountWorker {
1117
1150
  }
1118
1151
 
1119
1152
  if (this.commandQueue && !shutdownCalled) {
1120
- this.commandQueue = this.buildCommandQueue();
1153
+ this.mergeCommandQueue();
1121
1154
  }
1122
1155
  }, 15000);
1123
1156
 
@@ -1272,6 +1305,7 @@ async function start(apiKey, apiUrl) {
1272
1305
  console.log('');
1273
1306
  startTime = Date.now();
1274
1307
  dashboardStarted = true;
1308
+ setDashboardActive(true);
1275
1309
  process.stdout.write(c.hide);
1276
1310
 
1277
1311
  setInterval(() => scheduleRender(), 1000);
@@ -1283,6 +1317,7 @@ async function start(apiKey, apiUrl) {
1283
1317
  sigintHandled = true;
1284
1318
  shutdownCalled = true;
1285
1319
  dashboardStarted = false;
1320
+ setDashboardActive(false);
1286
1321
  process.stdout.write(c.show);
1287
1322
 
1288
1323
  // Clear the dashboard area before printing summary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dankgrinder",
3
- "version": "4.3.0",
3
+ "version": "4.3.1",
4
4
  "description": "Dank Memer automation engine — grind coins while you sleep",
5
5
  "bin": {
6
6
  "dankgrinder": "bin/dankgrinder.js"