dankgrinder 8.94.0 → 8.95.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.
- package/lib/grinder.js +21 -1
- package/lib/rawLogger.js +32 -4
- package/package.json +1 -1
package/lib/grinder.js
CHANGED
|
@@ -671,6 +671,7 @@ class AccountWorker {
|
|
|
671
671
|
this._levelQuestQueue = [];
|
|
672
672
|
this._levelQuestDone = new Set();
|
|
673
673
|
this._questBetOverride = null;
|
|
674
|
+
this._commandRunning = false; // prevents grinding commands from overlapping with quest commands
|
|
674
675
|
this.commandQueue = null;
|
|
675
676
|
this.lastHealthCheck = Date.now();
|
|
676
677
|
this.doneToday = new Map();
|
|
@@ -1729,8 +1730,11 @@ class AccountWorker {
|
|
|
1729
1730
|
// Detect level-locked command → start quest mode
|
|
1730
1731
|
if (cmdResult.levelLocked) {
|
|
1731
1732
|
const targetLv = cmdResult.levelLocked;
|
|
1733
|
+
this.log('warn', `Command /${cmdName} is LOCKED at Level ${targetLv} — starting quest unlock flow`);
|
|
1732
1734
|
if (this._startLevelQuests(targetLv)) {
|
|
1733
|
-
this.log('info', `[QUEST]
|
|
1735
|
+
this.log('info', `[QUEST] Quest mode activated for Level ${targetLv} — grinding will resume after quests complete`);
|
|
1736
|
+
} else {
|
|
1737
|
+
this.log('warn', `[QUEST] Level ${targetLv} quests already done or not defined — grinding continues (may re-trigger)`);
|
|
1734
1738
|
}
|
|
1735
1739
|
}
|
|
1736
1740
|
|
|
@@ -1908,7 +1912,12 @@ class AccountWorker {
|
|
|
1908
1912
|
this._levelQuestQueue = quests.map(q => ({ ...q, level: targetLevel }));
|
|
1909
1913
|
this._levelQuestActive = true;
|
|
1910
1914
|
this._questBetOverride = null;
|
|
1915
|
+
// Clear commandQueue so no stale grinding commands fire after quests finish
|
|
1916
|
+
this.commandQueue = null;
|
|
1917
|
+
this._commandRunning = false; // cancel any in-flight grinding command
|
|
1911
1918
|
this.log('info', `[QUEST] Level ${targetLevel} quests started — grinding PAUSED`);
|
|
1919
|
+
const questList = this._levelQuestQueue.map(q => `"${q.cmd}" x${q.times}`).join(', ');
|
|
1920
|
+
this.log('info', `[QUEST] Quests: ${questList}`);
|
|
1912
1921
|
return true;
|
|
1913
1922
|
}
|
|
1914
1923
|
|
|
@@ -2169,7 +2178,11 @@ class AccountWorker {
|
|
|
2169
2178
|
const prefix = this.account.use_slash ? '/' : 'pls';
|
|
2170
2179
|
this.setStatus(`[L${quest.level}] QUEST ${quest.cmd} (${quest.times}x left)`);
|
|
2171
2180
|
this.lastStatus = `[L${quest.level}] ${quest.cmd}`;
|
|
2181
|
+
this._commandRunning = true;
|
|
2182
|
+
this.busy = true; // also set busy so grinding tick path blocks while quest runs
|
|
2172
2183
|
await this.runCommand(quest.cmd, prefix);
|
|
2184
|
+
this._commandRunning = false;
|
|
2185
|
+
this.busy = false;
|
|
2173
2186
|
this._questBetOverride = null;
|
|
2174
2187
|
quest.times--;
|
|
2175
2188
|
if (quest.times <= 0) this._levelQuestQueue.shift();
|
|
@@ -2177,6 +2190,8 @@ class AccountWorker {
|
|
|
2177
2190
|
this._levelQuestActive = false;
|
|
2178
2191
|
this._levelQuestDone.add(quest.level);
|
|
2179
2192
|
this.log('success', `[QUEST] Level ${quest.level} quests DONE — resuming grinding`);
|
|
2193
|
+
// Null out commandQueue so buildCommandQueue picks only unlocked commands
|
|
2194
|
+
this.commandQueue = null;
|
|
2180
2195
|
this.setStatus('idle');
|
|
2181
2196
|
}
|
|
2182
2197
|
this.tickTimeout = setTimeout(() => this.tick(), 2500);
|
|
@@ -2198,6 +2213,11 @@ class AccountWorker {
|
|
|
2198
2213
|
this.tickTimeout = setTimeout(() => this.tick(), 2000);
|
|
2199
2214
|
return;
|
|
2200
2215
|
}
|
|
2216
|
+
// Block grinding if a quest command is currently running (race condition guard)
|
|
2217
|
+
if (this._commandRunning) {
|
|
2218
|
+
this.tickTimeout = setTimeout(() => this.tick(), 1500);
|
|
2219
|
+
return;
|
|
2220
|
+
}
|
|
2201
2221
|
|
|
2202
2222
|
const now = Date.now();
|
|
2203
2223
|
|
package/lib/rawLogger.js
CHANGED
|
@@ -528,14 +528,42 @@ function attachDmLogger(client, opts = {}) {
|
|
|
528
528
|
if (targetAuthorId && d.author?.id !== targetAuthorId) return;
|
|
529
529
|
|
|
530
530
|
const content = d.content || '';
|
|
531
|
+
// Also extract individual embed field values for richer level-up detection
|
|
532
|
+
const embedFieldsText = (d.embeds || []).map(e => {
|
|
533
|
+
const fields = (e.fields || []).map(f => `${f.name || ''} ${f.value || ''}`).join('\n');
|
|
534
|
+
return `${e.title || ''} ${e.description || ''} ${e.footer?.text || ''} ${e.author?.name || ''} ${fields}`;
|
|
535
|
+
}).join('\n');
|
|
531
536
|
const embedText = extractEmbedText(d.embeds).toLowerCase();
|
|
532
|
-
const allText = (content + '\n' + embedText).toLowerCase();
|
|
537
|
+
const allText = (content + '\n' + embedFieldsText + '\n' + embedText).toLowerCase();
|
|
533
538
|
|
|
534
539
|
// Detect event type
|
|
535
540
|
let dmEvent = null;
|
|
536
|
-
if (allText.includes('leveled up') || allText.includes('level up')) {
|
|
537
|
-
|
|
538
|
-
|
|
541
|
+
if (allText.includes('leveled up') || allText.includes('level up') || allText.includes('to level')) {
|
|
542
|
+
// Try multiple level-up patterns (Dank Memer varies the message format):
|
|
543
|
+
// "You leveled up from level X to Y"
|
|
544
|
+
// "You leveled up! You're now level Y"
|
|
545
|
+
// "You are now level Y"
|
|
546
|
+
// "You advanced to level Y"
|
|
547
|
+
// "Congratulations! Level Y"
|
|
548
|
+
let fromLv = 0, toLv = 0;
|
|
549
|
+
const m1 = allText.match(/level\s+(\d+)\s+to\s+level?\s*(\d+)/i);
|
|
550
|
+
const m2 = allText.match(/leveled?\s*up[!\s]+(?:.*?)?(?:to\s+)?(?:level\s+)?(\d+)/i);
|
|
551
|
+
const m3 = allText.match(/(?:you(?:'re| are) now|now at|advanced? to|reached|congratulations.*?level)\s+(?:level\s+)?(\d+)/i);
|
|
552
|
+
const m4 = allText.match(/(?:now\s+)?(?:at\s+)?level\s*(\d+)/i);
|
|
553
|
+
const m5 = allText.match(/to level\s*(\d+)/i);
|
|
554
|
+
|
|
555
|
+
if (m1) { fromLv = parseInt(m1[1]); toLv = parseInt(m1[2]); }
|
|
556
|
+
else if (m2) { toLv = parseInt(m2[1]); }
|
|
557
|
+
else if (m3) { toLv = parseInt(m3[1]); }
|
|
558
|
+
else if (m4) { toLv = parseInt(m4[1]); }
|
|
559
|
+
else if (m5) { toLv = parseInt(m5[1]); }
|
|
560
|
+
|
|
561
|
+
if (toLv > 0) {
|
|
562
|
+
dmEvent = { type: 'levelup', from: fromLv, to: toLv };
|
|
563
|
+
} else if ((allText.includes('leveled up') || allText.includes('level up')) && verboseMode) {
|
|
564
|
+
// Level-up keyword found but no number matched — log for debugging
|
|
565
|
+
console.log(` [DM LEVELUP] detected keyword but no number matched in: "${allText.substring(0, 200)}"`);
|
|
566
|
+
}
|
|
539
567
|
} else if (allText.includes('lifesaver protected') || allText.includes('you died')) {
|
|
540
568
|
// Parse lifesaver count from button labels: "You have 0 Life Saver left"
|
|
541
569
|
let lsLeft = -1;
|