dankgrinder 8.46.0 → 8.49.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 +3 -3
- package/lib/ui.js +17 -43
- package/package.json +1 -1
package/lib/grinder.js
CHANGED
|
@@ -2932,7 +2932,6 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
2932
2932
|
ui.log(-1, `Starting ${activeWorkers.length} grind loops...`);
|
|
2933
2933
|
ui.setLive(true);
|
|
2934
2934
|
ui.draw();
|
|
2935
|
-
ui.startRefresh(3000);
|
|
2936
2935
|
for (const w of activeWorkers) {
|
|
2937
2936
|
if (!shutdownCalled) w.grindLoop();
|
|
2938
2937
|
}
|
|
@@ -3003,7 +3002,6 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
3003
3002
|
shutdownInProgress = true;
|
|
3004
3003
|
shutdownCalled = true;
|
|
3005
3004
|
setDashboardActive(false);
|
|
3006
|
-
ui.stopRefresh();
|
|
3007
3005
|
ui.stop();
|
|
3008
3006
|
process.stdout.write(c.show + '\n');
|
|
3009
3007
|
|
|
@@ -3050,10 +3048,12 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
3050
3048
|
const webhookMsg = `+⏣ ${finalCoins.toLocaleString()} | ${finalCmds} cmds | ${formatUptime()}` +
|
|
3051
3049
|
(totalRecoveries > 0 ? ` | ${totalRecoveries} auto-recoveries` : '') +
|
|
3052
3050
|
(CLUSTER_ENABLED ? ` | node: ${NODE_ID.substring(0, 12)}` : '');
|
|
3053
|
-
sendWebhook('Session Ended', webhookMsg, 0x8b5cf6);
|
|
3051
|
+
sendWebhook('Session Ended', webhookMsg, 0x8b5cf6).catch(() => {});
|
|
3054
3052
|
|
|
3055
3053
|
if (redis) { redis.disconnect().catch(() => {}); }
|
|
3056
3054
|
console.log(`${c.green}Goodbye!${c.reset}\n`);
|
|
3055
|
+
// Force exit after 5s so Ctrl+C always terminates even if cleanup hangs
|
|
3056
|
+
setTimeout(() => process.exit(0), 5000);
|
|
3057
3057
|
process.exit(0);
|
|
3058
3058
|
}
|
|
3059
3059
|
|
package/lib/ui.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI Live Dashboard — ASCII banner, per-account status table, event stream below.
|
|
3
|
+
* Box fixed at top. Events append line-by-line below. Manual redraw only.
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
let _startTime = Date.now();
|
|
@@ -8,10 +9,6 @@ let _isShuttingDown = () => false;
|
|
|
8
9
|
let _version = '0.0.0';
|
|
9
10
|
let _live = false;
|
|
10
11
|
let _phase = 'init'; // 'init' | 'login' | 'inventory' | 'balance' | 'dms' | 'grinding'
|
|
11
|
-
let _boxRow = 0; // which terminal row the box top starts on
|
|
12
|
-
let _boxHeight = 0; // total rows consumed by the box
|
|
13
|
-
let _eventCountAtDraw = 0; // events logged since last draw
|
|
14
|
-
let _eventCount = 0; // total events ever logged
|
|
15
12
|
|
|
16
13
|
// ── Spinner frames ────────────────────────────────────────────
|
|
17
14
|
const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
@@ -20,7 +17,7 @@ function spinnerFrame() { return SPINNER[Math.floor(Date.now() / 150) % SPINNER.
|
|
|
20
17
|
// ── Compact ASCII art banner (fits in 80-col box) ─────────────
|
|
21
18
|
const BANNER_LINES = [
|
|
22
19
|
' ██████╗ ██╗ ██╗███╗ ██╗ ██████╗ ███████╗ ██████╗ ███╗ ██╗ DANKGRINDER',
|
|
23
|
-
' ██╔══██╗██║ ██║████╗ ██║██╔════╝ ██╔════╝██╔═══██╗████╗ ██║
|
|
20
|
+
' ██╔══██╗██║ ██║████╗ ██║██╔════╝ ██╔════╝██╔═══██╗████╗ ██║ vPLACEHOLDER',
|
|
24
21
|
' ██║ ██║██║ ██║██╔██╗ ██║██║ ███╗█████╗ ██║ ██║██╔██╗ ██║',
|
|
25
22
|
' ██║ ██║██║ ██║██║╚██╗██║██║ ██║██╔══╝ ██║ ██║██║╚██╗██║',
|
|
26
23
|
' ██████╔╝╚██████╔╝██║ ╚████║╚██████╔╝███████╗╚██████╔╝██║ ╚████║',
|
|
@@ -123,27 +120,18 @@ function draw() {
|
|
|
123
120
|
const { W, maxAccounts } = layout();
|
|
124
121
|
const inner = W - 2;
|
|
125
122
|
|
|
126
|
-
// ── Clear screen + home ──
|
|
127
|
-
|
|
128
|
-
if (isFirst) {
|
|
129
|
-
process.stdout.write('\x1b[2J\x1b[H');
|
|
130
|
-
} else {
|
|
131
|
-
// Move cursor up to box start: box rows + events since last draw
|
|
132
|
-
const eventsSinceDraw = _eventCount - _eventCountAtDraw;
|
|
133
|
-
const up = _boxHeight + eventsSinceDraw;
|
|
134
|
-
process.stdout.write(`\x1b[${up}A`);
|
|
135
|
-
}
|
|
123
|
+
// ── Clear screen + home (always from top — keeps box fixed) ──
|
|
124
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
136
125
|
|
|
137
126
|
// ── Top border ──
|
|
138
127
|
process.stdout.write(`\x1b[38;2;77;212;238m┌${'─'.repeat(inner)}┐\x1b[0m\n`);
|
|
139
128
|
|
|
140
|
-
// ── ASCII banner
|
|
129
|
+
// ── ASCII banner ──
|
|
141
130
|
const bannerWithVer = BANNER_LINES[1].replace('PLACEHOLDER', _version);
|
|
142
131
|
const bannerLines = [BANNER_LINES[0], bannerWithVer, ...BANNER_LINES.slice(2)];
|
|
143
132
|
|
|
144
133
|
for (let i = 0; i < bannerLines.length; i++) {
|
|
145
134
|
const line = bannerLines[i];
|
|
146
|
-
// Gradient: cyan → pink for row 0 and 1, dim for others
|
|
147
135
|
if (i < 2) {
|
|
148
136
|
const gradLine = gradientLine(line, 77, 212, 238, 255, 92, 147);
|
|
149
137
|
const pad = ' '.repeat(Math.max(0, inner - stripAnsi(gradLine).length));
|
|
@@ -252,10 +240,6 @@ function draw() {
|
|
|
252
240
|
|
|
253
241
|
// ── Bottom ──
|
|
254
242
|
process.stdout.write(`\x1b[38;2;77;212;238m└${'─'.repeat(inner)}┘\x1b[0m\n`);
|
|
255
|
-
|
|
256
|
-
// Record box height + current event count for next redraw
|
|
257
|
-
_boxHeight = bannerLines.length + 1 + 1 + 2 + shown.length + (sorted.length > maxAccounts ? 1 : 0) + 3;
|
|
258
|
-
_eventCountAtDraw = _eventCount;
|
|
259
243
|
}
|
|
260
244
|
|
|
261
245
|
// ── Gradient line ─────────────────────────────────────────────
|
|
@@ -270,7 +254,7 @@ function gradientLine(text, r1, g1, b1, r2, g2, b2) {
|
|
|
270
254
|
|
|
271
255
|
// ── Event tracking ────────────────────────────────────────────
|
|
272
256
|
let _eventLines = []; // [accountIdx] = [{text, ts}]
|
|
273
|
-
const MAX_EVENTS =
|
|
257
|
+
const MAX_EVENTS = 20; // keep last 20 events per account
|
|
274
258
|
|
|
275
259
|
// ── Public API ────────────────────────────────────────────────
|
|
276
260
|
|
|
@@ -282,22 +266,22 @@ function init({ workers, isShuttingDown }) {
|
|
|
282
266
|
_eventLines = [];
|
|
283
267
|
_live = false;
|
|
284
268
|
_phase = 'init';
|
|
285
|
-
_boxRow = 0;
|
|
286
|
-
_boxHeight = 0;
|
|
287
|
-
_eventCount = 0;
|
|
288
|
-
_eventCountAtDraw = 0;
|
|
289
269
|
}
|
|
290
270
|
|
|
291
271
|
function drawBanner(version) { _version = version || '0.0.0'; }
|
|
292
272
|
|
|
293
273
|
function start() {}
|
|
294
|
-
function stop() {
|
|
274
|
+
function stop() {
|
|
275
|
+
_live = false;
|
|
276
|
+
_phase = 'init';
|
|
277
|
+
// Clear screen on shutdown so box disappears
|
|
278
|
+
process.stdout.write('\x1b[2J\x1b[H' + c.reset + '\n');
|
|
279
|
+
}
|
|
295
280
|
|
|
296
281
|
function setLive(val) { _live = val; }
|
|
297
|
-
|
|
298
282
|
function setPhase(phase) { _phase = phase; }
|
|
299
283
|
|
|
300
|
-
// log: append event below
|
|
284
|
+
// log: draw box + append event below it
|
|
301
285
|
function log(accountIdx, msg) {
|
|
302
286
|
const now = new Date();
|
|
303
287
|
const ts = `${padL(now.getHours(), 2, '0')}:${padL(now.getMinutes(), 2, '0')}:${padL(now.getSeconds(), 2, '0')}`;
|
|
@@ -307,11 +291,11 @@ function log(accountIdx, msg) {
|
|
|
307
291
|
_eventLines[accountIdx].push({ text: msg, ts });
|
|
308
292
|
if (_eventLines[accountIdx].length > MAX_EVENTS) _eventLines[accountIdx].shift();
|
|
309
293
|
}
|
|
310
|
-
_eventCount++;
|
|
311
294
|
|
|
312
295
|
if (!_live) return;
|
|
313
296
|
|
|
314
|
-
//
|
|
297
|
+
// Redraw the whole box (clears screen + redraws at top) then append event
|
|
298
|
+
draw();
|
|
315
299
|
const col2 = accountIdx >= 0 ? wc(accountIdx) : c.cyan;
|
|
316
300
|
const name = accountIdx >= 0 ? trunc(_workers[accountIdx]?.username || '?', 14) : 'GLOBAL';
|
|
317
301
|
process.stdout.write(`${col2}${name}${c.reset} ${DIM}[${ts}]${c.reset} ${msg}\n`);
|
|
@@ -319,16 +303,6 @@ function log(accountIdx, msg) {
|
|
|
319
303
|
|
|
320
304
|
function logGlobal(msg) { log(-1, msg); }
|
|
321
305
|
|
|
322
|
-
//
|
|
323
|
-
let _refreshInterval = null;
|
|
324
|
-
function startRefresh(ms = 3000) {
|
|
325
|
-
if (_refreshInterval) clearInterval(_refreshInterval);
|
|
326
|
-
_refreshInterval = setInterval(() => {
|
|
327
|
-
if (_live) draw();
|
|
328
|
-
}, ms);
|
|
329
|
-
}
|
|
330
|
-
function stopRefresh() {
|
|
331
|
-
if (_refreshInterval) { clearInterval(_refreshInterval); _refreshInterval = null; }
|
|
332
|
-
}
|
|
306
|
+
// Periodic refresh removed — draw() is now only called explicitly
|
|
333
307
|
|
|
334
|
-
module.exports = { init, drawBanner, start, draw, log, logGlobal, workerColor: wc, stop, setLive, setPhase
|
|
308
|
+
module.exports = { init, drawBanner, start, draw, log, logGlobal, workerColor: wc, stop, setLive, setPhase };
|