dankgrinder 8.91.0 → 8.93.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 +85 -7
- package/lib/rawLogger.js +6 -1
- package/package.json +1 -1
package/lib/grinder.js
CHANGED
|
@@ -665,6 +665,12 @@ class AccountWorker {
|
|
|
665
665
|
this._sellRunning = false;
|
|
666
666
|
this.failStreak = 0;
|
|
667
667
|
this.globalCooldownUntil = 0;
|
|
668
|
+
// Level quest system — blocks grinding until quests complete
|
|
669
|
+
this._level = 1;
|
|
670
|
+
this._levelQuestActive = false;
|
|
671
|
+
this._levelQuestQueue = [];
|
|
672
|
+
this._levelQuestDone = new Set();
|
|
673
|
+
this._questBetOverride = null;
|
|
668
674
|
this.commandQueue = null;
|
|
669
675
|
this.lastHealthCheck = Date.now();
|
|
670
676
|
this.doneToday = new Map();
|
|
@@ -1479,7 +1485,7 @@ class AccountWorker {
|
|
|
1479
1485
|
client: this.client,
|
|
1480
1486
|
safeAnswers: cmdName === 'search' ? safeParseJSON(this.account.search_answers, []) :
|
|
1481
1487
|
cmdName === 'crime' ? safeParseJSON(this.account.crime_answers, []) : [],
|
|
1482
|
-
betAmount: ['blackjack'].includes(cmdName) ? bjBet : gambBet,
|
|
1488
|
+
betAmount: this._questBetOverride || (['blackjack'].includes(cmdName) ? bjBet : gambBet),
|
|
1483
1489
|
accountId: this.account.id,
|
|
1484
1490
|
redis,
|
|
1485
1491
|
};
|
|
@@ -1538,6 +1544,18 @@ class AccountWorker {
|
|
|
1538
1544
|
return;
|
|
1539
1545
|
}
|
|
1540
1546
|
|
|
1547
|
+
// Level-locked detection — check rawLogger (CV2/embed text) NOT just content
|
|
1548
|
+
const raw = rawLogger.getLastRaw(this.channel?.id);
|
|
1549
|
+
const rawAllText = (raw?.content || '') + '\n' + (raw?.cv2Text || '') + '\n' + (raw?.embedText || '');
|
|
1550
|
+
if (rawAllText.toLowerCase().includes('not unlocked')) {
|
|
1551
|
+
const lvMatch = rawAllText.match(/level\s*(\d+)/i);
|
|
1552
|
+
if (lvMatch) {
|
|
1553
|
+
const targetLv = parseInt(lvMatch[1]);
|
|
1554
|
+
cmdResult.levelLocked = targetLv;
|
|
1555
|
+
this.log('warn', `Command /${cmdName} requires Level ${targetLv} quests`);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1541
1559
|
// Captcha/verification detection — Aho-Corasick O(n) single-pass match
|
|
1542
1560
|
// Instead of 8 separate .includes() calls (each O(n)), one automaton pass
|
|
1543
1561
|
if (captchaDetector.hasAny(resultLower)) {
|
|
@@ -1708,6 +1726,14 @@ class AccountWorker {
|
|
|
1708
1726
|
this.globalCooldownUntil = Math.max(this.globalCooldownUntil, Date.now() + holdSec * 1000);
|
|
1709
1727
|
}
|
|
1710
1728
|
|
|
1729
|
+
// Detect level-locked command → start quest mode
|
|
1730
|
+
if (cmdResult.levelLocked) {
|
|
1731
|
+
const targetLv = cmdResult.levelLocked;
|
|
1732
|
+
if (this._startLevelQuests(targetLv)) {
|
|
1733
|
+
this.log('info', `[QUEST] Detected locked command — target Level ${targetLv}`);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1711
1737
|
this.stats.successes++;
|
|
1712
1738
|
// Format result with clean command name and colored earnings
|
|
1713
1739
|
const formattedResult = formatCommandResult(cmdName, result, earned, spent);
|
|
@@ -1856,6 +1882,36 @@ class AccountWorker {
|
|
|
1856
1882
|
// Alert is NOT scheduled — it's reactive (listener-based, see grindLoop)
|
|
1857
1883
|
].map(Object.freeze);
|
|
1858
1884
|
|
|
1885
|
+
// ── Level Quest System — blocks grinding until quests complete ──
|
|
1886
|
+
static LEVEL_QUESTS = {
|
|
1887
|
+
1: [
|
|
1888
|
+
{ cmd: 'beg', times: 2 },
|
|
1889
|
+
{ cmd: 'search', times: 2 },
|
|
1890
|
+
{ cmd: 'tidy', times: 2 },
|
|
1891
|
+
],
|
|
1892
|
+
3: [
|
|
1893
|
+
{ cmd: 'work apply', times: 1 },
|
|
1894
|
+
{ cmd: 'work shift', times: 1 },
|
|
1895
|
+
{ cmd: 'shop sell common coin 1', times: 2 },
|
|
1896
|
+
],
|
|
1897
|
+
5: [
|
|
1898
|
+
{ cmd: 'slots', times: 1, bet: 50000 },
|
|
1899
|
+
{ cmd: 'cointoss', times: 1, bet: 50000 },
|
|
1900
|
+
{ cmd: 'snakeeyes', times: 1, bet: 50000 },
|
|
1901
|
+
],
|
|
1902
|
+
};
|
|
1903
|
+
|
|
1904
|
+
_startLevelQuests(targetLevel) {
|
|
1905
|
+
if (this._levelQuestDone.has(targetLevel)) return false;
|
|
1906
|
+
const quests = AccountWorker.LEVEL_QUESTS[targetLevel];
|
|
1907
|
+
if (!quests || quests.length === 0) return false;
|
|
1908
|
+
this._levelQuestQueue = quests.map(q => ({ ...q, level: targetLevel }));
|
|
1909
|
+
this._levelQuestActive = true;
|
|
1910
|
+
this._questBetOverride = null;
|
|
1911
|
+
this.log('info', `[QUEST] Level ${targetLevel} quests started — grinding PAUSED`);
|
|
1912
|
+
return true;
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1859
1915
|
async buildCommandQueue() {
|
|
1860
1916
|
const heap = new MinHeap();
|
|
1861
1917
|
const now = Date.now();
|
|
@@ -2106,6 +2162,27 @@ class AccountWorker {
|
|
|
2106
2162
|
|
|
2107
2163
|
// ── Main Non-Blocking Grind Scheduler ───────────────────────
|
|
2108
2164
|
async tick() {
|
|
2165
|
+
// BLOCK: quest mode active — run quests only, no normal grinding
|
|
2166
|
+
if (this._levelQuestActive && this._levelQuestQueue.length > 0) {
|
|
2167
|
+
const quest = this._levelQuestQueue[0];
|
|
2168
|
+
this._questBetOverride = quest.bet || null;
|
|
2169
|
+
const prefix = this.account.use_slash ? '/' : 'pls';
|
|
2170
|
+
this.setStatus(`[L${quest.level}] QUEST ${quest.cmd} (${quest.times}x left)`);
|
|
2171
|
+
this.lastStatus = `[L${quest.level}] ${quest.cmd}`;
|
|
2172
|
+
await this.runCommand(quest.cmd, prefix);
|
|
2173
|
+
this._questBetOverride = null;
|
|
2174
|
+
quest.times--;
|
|
2175
|
+
if (quest.times <= 0) this._levelQuestQueue.shift();
|
|
2176
|
+
if (this._levelQuestQueue.length === 0) {
|
|
2177
|
+
this._levelQuestActive = false;
|
|
2178
|
+
this._levelQuestDone.add(quest.level);
|
|
2179
|
+
this.log('success', `[QUEST] Level ${quest.level} quests DONE — resuming grinding`);
|
|
2180
|
+
this.setStatus('idle');
|
|
2181
|
+
}
|
|
2182
|
+
this.tickTimeout = setTimeout(() => this.tick(), 2500);
|
|
2183
|
+
return;
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2109
2186
|
if (!this.running || shutdownCalled) return;
|
|
2110
2187
|
if (this.paused) {
|
|
2111
2188
|
this.setStatus('PAUSED (captcha)');
|
|
@@ -3042,6 +3119,7 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
3042
3119
|
let shutdownInProgress = false;
|
|
3043
3120
|
|
|
3044
3121
|
async function gracefulShutdown(signal) {
|
|
3122
|
+
const chalk = require('chalk');
|
|
3045
3123
|
if (shutdownInProgress) return;
|
|
3046
3124
|
shutdownInProgress = true;
|
|
3047
3125
|
shutdownCalled = true;
|
|
@@ -3062,8 +3140,8 @@ const figlet = require('figlet');
|
|
|
3062
3140
|
let table = '';
|
|
3063
3141
|
|
|
3064
3142
|
|
|
3065
|
-
table += ' ' +
|
|
3066
|
-
table += ' ' +
|
|
3143
|
+
table += ' ' + chalk.dim('────────────────────────────────────────────────────────────────────────────────────────────────') + '\n\n';
|
|
3144
|
+
table += ' ' + chalk.dim('ACCOUNT'.padEnd(25)) + chalk.dim('GAINED'.padEnd(15)) + chalk.dim('COMMANDS'.padEnd(10)) + chalk.dim('OK %') + '\n\n';
|
|
3067
3145
|
|
|
3068
3146
|
for (const wk of workers) {
|
|
3069
3147
|
const rate = wk.stats.commands > 0 ? ((wk.stats.successes / wk.stats.commands) * 100).toFixed(0) : 0;
|
|
@@ -3087,14 +3165,14 @@ const figlet = require('figlet');
|
|
|
3087
3165
|
table += ` ${c.dim}${'No workers...'.padEnd(25)}${c.reset} ${''.padEnd(15)} ${''.padEnd(10)} ${''.padEnd(6)}\n`;
|
|
3088
3166
|
}
|
|
3089
3167
|
|
|
3090
|
-
table += '\n ' +
|
|
3168
|
+
table += '\n ' + chalk.dim('────────────────────────────────────────────────────────────────────────────────────────────────') + '\n';
|
|
3091
3169
|
process.stdout.write(table);
|
|
3092
3170
|
|
|
3093
3171
|
const memFinal = Math.round((process.memoryUsage?.rss?.() ?? process.memoryUsage().rss) / 1048576);
|
|
3094
3172
|
const cpm = globalCmdRate.getRate().toFixed(1);
|
|
3095
3173
|
|
|
3096
|
-
console.log('\n ' +
|
|
3097
|
-
console.log(' ' +
|
|
3174
|
+
console.log('\n ' + chalk.magenta('◆') + ' ' + chalk.bold('TOTAL') + ' ' + chalk.green('+⏣' + finalCoins.toLocaleString()) + ' ' + chalk.dim('in ' + ui.formatUptime()));
|
|
3175
|
+
console.log(' ' + chalk.cyan('◆') + ' ' + chalk.bold('STATS') + ' ' + finalCmds + chalk.dim(' cmds │ ') + '~' + cpm + chalk.dim(' cmd/m │ ') + memFinal + chalk.dim('MB RAM'));
|
|
3098
3176
|
console.log('\n');
|
|
3099
3177
|
|
|
3100
3178
|
|
|
@@ -3127,7 +3205,7 @@ const figlet = require('figlet');
|
|
|
3127
3205
|
|
|
3128
3206
|
const disResult = redis?.disconnect?.();
|
|
3129
3207
|
if (disResult && typeof disResult.catch === 'function') disResult.catch(() => {});
|
|
3130
|
-
console.log(
|
|
3208
|
+
console.log(chalk.magenta + figlet.textSync('GOODBYE!', { font: 'ANSI Shadow' }) + c.reset + '\n');
|
|
3131
3209
|
// Force exit so Ctrl+C always terminates immediately
|
|
3132
3210
|
setTimeout(() => process.exit(0), 2000);
|
|
3133
3211
|
process.exit(0);
|
package/lib/rawLogger.js
CHANGED
|
@@ -294,7 +294,11 @@ function detectCommand(d) {
|
|
|
294
294
|
if (anyOf(embedText, ['fishing', 'fish'])) return 'fish';
|
|
295
295
|
if (has(embedText, 'hold tight')) return 'holdtight';
|
|
296
296
|
|
|
297
|
-
//
|
|
297
|
+
// Level-gated command lock
|
|
298
|
+
if (anyOf(allText, ['not unlocked', 'complete tasks to unlock'])) {
|
|
299
|
+
const lvMatch = allText.match(/level\s*(\d+)/i);
|
|
300
|
+
return lvMatch ? 'level_locked' : 'unknown';
|
|
301
|
+
}
|
|
298
302
|
if (anyOf(allText, ['hunting', 'went hunting', 'hunting rifle', 'your aim was so bad', 'animals laughed', 'animals attacked', 'barely escaped', 'fell asleep in a tree', 'caught nothing', 'brought back literally nothing', 'rifle broke', 'imagine going into the woods'])) return 'hunt';
|
|
299
303
|
if (anyOf(allText, ['digging', 'you dug', 'dug in the dirt', 'found nothing while', 'what are the odds lol'])) return 'dig';
|
|
300
304
|
if (anyOf(allText, ['brought back']) && anyOf(allText, ['ant', 'worm', 'stickbug', 'ladybug'])) return 'dig';
|
|
@@ -712,6 +716,7 @@ module.exports = {
|
|
|
712
716
|
onDmEvent,
|
|
713
717
|
onNextEphemeral,
|
|
714
718
|
setVerbose,
|
|
719
|
+
store,
|
|
715
720
|
// Memory reads
|
|
716
721
|
getRawMessage,
|
|
717
722
|
getLastRaw,
|