dankgrinder 8.78.0 → 8.80.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 +23 -17
- package/lib/ui.js +9 -1
- package/package.json +1 -1
package/lib/grinder.js
CHANGED
|
@@ -744,8 +744,10 @@ class AccountWorker {
|
|
|
744
744
|
const self = this;
|
|
745
745
|
function cleanup() {
|
|
746
746
|
clearTimeout(timer);
|
|
747
|
-
self.client
|
|
748
|
-
|
|
747
|
+
if (self.client) {
|
|
748
|
+
self.client.removeListener('messageCreate', handler);
|
|
749
|
+
self.client.removeListener('messageUpdate', updateHandler);
|
|
750
|
+
}
|
|
749
751
|
}
|
|
750
752
|
function handler(msg) {
|
|
751
753
|
if (msg.author.id === DANK_MEMER_ID && msg.channel.id === self.channel.id) {
|
|
@@ -2738,34 +2740,38 @@ captchaDetector.build();
|
|
|
2738
2740
|
async function start(apiKey, apiUrl, opts = {}) {
|
|
2739
2741
|
ui.init({ workers, isShuttingDown: () => shutdownCalled });
|
|
2740
2742
|
ui.drawBanner(PKG_VERSION);
|
|
2743
|
+
ui.setLive(true);
|
|
2744
|
+
ui.startRefresh();
|
|
2745
|
+
|
|
2741
2746
|
CLOUD_ADMIN_KEY = process.env.CLOUD_ADMIN_KEY || '';
|
|
2742
2747
|
API_KEY = apiKey;
|
|
2743
2748
|
API_URL = apiUrl || process.env.DANKGRINDER_URL || 'http://localhost:3000';
|
|
2744
2749
|
const CLOUD_MODE = opts.cloud === true;
|
|
2745
2750
|
|
|
2746
2751
|
if (CLOUD_MODE) {
|
|
2747
|
-
|
|
2752
|
+
ui.log(-1, 'Starting in CLOUD MODE');
|
|
2748
2753
|
}
|
|
2749
2754
|
REDIS_URL = process.env.REDIS_URL || '';
|
|
2750
2755
|
WEBHOOK_URL = process.env.WEBHOOK_URL || '';
|
|
2751
2756
|
|
|
2752
2757
|
const tw = 80;
|
|
2753
2758
|
|
|
2754
|
-
|
|
2755
|
-
|
|
2759
|
+
ui.log(-1, `DankGrinder v${PKG_VERSION} (${AccountWorker.COMMAND_MAP.length} cmds) mapped`);
|
|
2760
|
+
ui.log(-1, 'Fetching proxy node configs...');
|
|
2756
2761
|
|
|
2757
2762
|
const fetchOpts = CLOUD_MODE ? { cloud: true } : {};
|
|
2758
2763
|
let data = await fetchConfig(4, 2000, fetchOpts);
|
|
2759
2764
|
while (!data) {
|
|
2760
|
-
|
|
2765
|
+
ui.log(-1, 'Cannot connect to API - retrying in 10s...');
|
|
2761
2766
|
await new Promise((r) => setTimeout(r, 10000));
|
|
2762
2767
|
data = await fetchConfig(4, 2000, fetchOpts);
|
|
2763
2768
|
}
|
|
2764
2769
|
if (data && data.error) {
|
|
2765
|
-
|
|
2770
|
+
ui.log(-1, `API error: ${data.error}`);
|
|
2771
|
+
setTimeout(() => ui.stop(), 500);
|
|
2766
2772
|
return;
|
|
2767
2773
|
}
|
|
2768
|
-
|
|
2774
|
+
ui.log(-1, `Resolved ${data.accounts?.length || 0} accounts from database`);
|
|
2769
2775
|
|
|
2770
2776
|
// Cloud mode: post heartbeat every 30s
|
|
2771
2777
|
if (CLOUD_MODE) {
|
|
@@ -2784,7 +2790,7 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
2784
2790
|
};
|
|
2785
2791
|
postHeartbeat();
|
|
2786
2792
|
setInterval(postHeartbeat, CLOUD_HEARTBEAT_MS);
|
|
2787
|
-
log(
|
|
2793
|
+
ui.log(-1, 'Cloud heartbeat started');
|
|
2788
2794
|
}
|
|
2789
2795
|
|
|
2790
2796
|
// Pull Redis/Webhook URLs from API config if not in env
|
|
@@ -2796,18 +2802,19 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
2796
2802
|
|
|
2797
2803
|
let { accounts } = data;
|
|
2798
2804
|
if (!accounts || accounts.length === 0) {
|
|
2799
|
-
|
|
2805
|
+
ui.log(-1, 'No active accounts. Add them in the dashboard.');
|
|
2806
|
+
setTimeout(() => ui.stop(), 500);
|
|
2800
2807
|
return;
|
|
2801
2808
|
}
|
|
2802
|
-
|
|
2809
|
+
ui.log(-1, `Processing ${accounts.length} accounts...`);
|
|
2803
2810
|
|
|
2804
2811
|
// Cluster mode: filter to only accounts this node can claim
|
|
2805
2812
|
if (CLUSTER_ENABLED) {
|
|
2806
2813
|
const totalBefore = accounts.length;
|
|
2807
2814
|
accounts = await filterClaimableAccounts(accounts);
|
|
2808
|
-
|
|
2815
|
+
ui.log(-1, `Cluster Node: claimed ${accounts.length}/${totalBefore} accounts`);
|
|
2809
2816
|
if (accounts.length === 0) {
|
|
2810
|
-
|
|
2817
|
+
ui.log(-1, 'All accounts claimed by other nodes. Waiting...');
|
|
2811
2818
|
}
|
|
2812
2819
|
}
|
|
2813
2820
|
|
|
@@ -2968,9 +2975,7 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
2968
2975
|
// ── Phase 3: Start grind loops ───────────────────────────────────
|
|
2969
2976
|
ui.setPhase('grinding');
|
|
2970
2977
|
ui.log(-1, `Starting ${activeWorkers.length} grind loops...`);
|
|
2971
|
-
|
|
2972
|
-
ui.draw();
|
|
2973
|
-
ui.startRefresh();
|
|
2978
|
+
|
|
2974
2979
|
for (const w of activeWorkers) {
|
|
2975
2980
|
if (!shutdownCalled) w.grindLoop();
|
|
2976
2981
|
}
|
|
@@ -3089,7 +3094,8 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
3089
3094
|
(CLUSTER_ENABLED ? ` | node: ${NODE_ID.substring(0, 12)}` : '');
|
|
3090
3095
|
sendWebhook('Session Ended', webhookMsg, 0x8b5cf6).catch(() => {});
|
|
3091
3096
|
|
|
3092
|
-
|
|
3097
|
+
const disResult = redis?.disconnect?.();
|
|
3098
|
+
if (disResult && typeof disResult.catch === 'function') disResult.catch(() => {});
|
|
3093
3099
|
console.log(`${c.green}Goodbye!${c.reset}\n`);
|
|
3094
3100
|
// Force exit so Ctrl+C always terminates immediately
|
|
3095
3101
|
setTimeout(() => process.exit(0), 2000);
|
package/lib/ui.js
CHANGED
|
@@ -83,8 +83,16 @@ function addEvent(type, msg) {
|
|
|
83
83
|
if (_live) render();
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
|
|
87
|
+
|
|
86
88
|
function logGlobal(msg) { addEvent('info', msg); }
|
|
87
|
-
function log(accountIdx, msg) {
|
|
89
|
+
function log(accountIdx, msg) {
|
|
90
|
+
if (accountIdx === -1) {
|
|
91
|
+
if (_live) addEvent('info', msg.replace(/\x1b\[[0-9;]*m/g, ''));
|
|
92
|
+
else console.log(chalk.bold(msg));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
88
96
|
function updateAccountRow() { }
|
|
89
97
|
|
|
90
98
|
// Precision width padding
|