dankgrinder 7.58.0 → 7.62.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/commands/market.js +16 -12
- package/lib/grinder.js +10 -8
- package/package.json +1 -1
package/lib/commands/market.js
CHANGED
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
* Handles sell listings with optional partial sales and privacy settings.
|
|
5
5
|
*
|
|
6
6
|
* Dank Memer market post format:
|
|
7
|
-
* pls market post for_coins <listing_type> <qty> <item> <price>
|
|
7
|
+
* pls market post for_coins <listing_type> <qty> <item> <price>
|
|
8
|
+
* <allow_partial> <is_private> <partial_min> <days>
|
|
8
9
|
*
|
|
9
10
|
* listing_type: "sell" | "auction"
|
|
10
11
|
* allow_partial: "true" | "false"
|
|
11
12
|
* is_private: "true" | "false"
|
|
12
|
-
* partial_min:
|
|
13
|
+
* partial_min: integer ≥ 1
|
|
14
|
+
* days: 1-7
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
17
|
const {
|
|
@@ -48,17 +50,19 @@ async function runMarketPost({
|
|
|
48
50
|
return { result: 'no item specified', coins: 0 };
|
|
49
51
|
}
|
|
50
52
|
|
|
53
|
+
// Dank Memer expects: <qty> <item> <price> <allow_partial> <is_private> <days> <partial_min>
|
|
54
|
+
// Note: allow_partial and is_private come BEFORE days (verified via test-market.js)
|
|
51
55
|
const cmdParts = [
|
|
52
56
|
'pls', 'market', 'post',
|
|
53
|
-
'for_coins',
|
|
54
|
-
'sell',
|
|
55
|
-
String(quantity),
|
|
56
|
-
itemName,
|
|
57
|
-
String(pricePerItem * quantity),
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
String(
|
|
57
|
+
'for_coins', // price type: fixed price
|
|
58
|
+
'sell', // listing type
|
|
59
|
+
String(quantity), // quantity
|
|
60
|
+
itemName, // item name
|
|
61
|
+
String(pricePerItem * quantity), // TOTAL price
|
|
62
|
+
allowPartial ? 'true' : 'false', // allow partial
|
|
63
|
+
isPrivate ? 'true' : 'false', // is private
|
|
64
|
+
String(Math.max(1, partialMin || 1)), // partial minimum (always ≥1)
|
|
65
|
+
String(days), // days (1-7)
|
|
62
66
|
];
|
|
63
67
|
|
|
64
68
|
const cmdString = cmdParts.join(' ');
|
|
@@ -84,7 +88,7 @@ async function runMarketPost({
|
|
|
84
88
|
|
|
85
89
|
// Check for common errors
|
|
86
90
|
const lowerText = text.toLowerCase();
|
|
87
|
-
if (lowerText.includes('you don\'t have') || lowerText.includes('not enough') || lowerText.includes('invalid item') || lowerText.includes('partial minimum can\'t') || lowerText.includes('set allow_partial')) {
|
|
91
|
+
if (lowerText.includes('you don\'t have') || lowerText.includes('not enough') || lowerText.includes('invalid item') || lowerText.includes('partial minimum can\'t') || lowerText.includes('set allow_partial') || lowerText.includes('allow_partial is incorrect') || lowerText.includes('allow_partial')) {
|
|
88
92
|
return { result: text.substring(0, 80) || 'error listing item', coins: 0 };
|
|
89
93
|
}
|
|
90
94
|
|
package/lib/grinder.js
CHANGED
|
@@ -586,7 +586,7 @@ function renderDashboard() {
|
|
|
586
586
|
|
|
587
587
|
for (const wk of visibleWorkers) {
|
|
588
588
|
const origNum = (wk.idx + 1).toString().padStart(colNum);
|
|
589
|
-
const rawStat = (wk.lastStatus || '
|
|
589
|
+
const rawStat = (wk.lastStatus || 'ready').replace(RE, '');
|
|
590
590
|
const activityText = rawStat.substring(0, colActivity);
|
|
591
591
|
|
|
592
592
|
// ── Status icon ──
|
|
@@ -1133,6 +1133,7 @@ class AccountWorker {
|
|
|
1133
1133
|
this.lastRunTime = {};
|
|
1134
1134
|
this.cycleCount = 0;
|
|
1135
1135
|
this.lastCommandRun = 0;
|
|
1136
|
+
this.lastStatus = 'ready';
|
|
1136
1137
|
this.paused = false;
|
|
1137
1138
|
this.dashboardPaused = false;
|
|
1138
1139
|
this._sellRunning = false;
|
|
@@ -1815,7 +1816,8 @@ class AccountWorker {
|
|
|
1815
1816
|
if (currentLevel > 0) {
|
|
1816
1817
|
await redis.set(`dkg:level:${this.account.id}`, String(currentLevel), 'EX', 2592000);
|
|
1817
1818
|
this._level = currentLevel;
|
|
1818
|
-
|
|
1819
|
+
// Only log to terminal during startup — after dashboardStarted, go to live feed
|
|
1820
|
+
if (dashboardStarted) this.log('info', `DM level: ${c.bold}${currentLevel}${c.reset}`);
|
|
1819
1821
|
}
|
|
1820
1822
|
if (lastLifesaverCount >= 0) {
|
|
1821
1823
|
await redis.set(`dkg:lifesavers:${this.account.id}`, String(lastLifesaverCount), 'EX', 86400);
|
|
@@ -1823,7 +1825,7 @@ class AccountWorker {
|
|
|
1823
1825
|
if (lastLifesaverCount === 0) {
|
|
1824
1826
|
await redis.set(`raw:alert:no-lifesaver:${dm.id}`, '1', 'EX', 86400);
|
|
1825
1827
|
await redis.set(`raw:alert:no-lifesaver:${this.channel?.id}`, '1', 'EX', 86400);
|
|
1826
|
-
this.log('error', `${c.red}0 LIFESAVERS! Crime/Search will be disabled.${c.reset}`);
|
|
1828
|
+
if (dashboardStarted) this.log('error', `${c.red}0 LIFESAVERS! Crime/Search will be disabled.${c.reset}`);
|
|
1827
1829
|
}
|
|
1828
1830
|
}
|
|
1829
1831
|
}
|
|
@@ -1836,7 +1838,7 @@ class AccountWorker {
|
|
|
1836
1838
|
}
|
|
1837
1839
|
}
|
|
1838
1840
|
}
|
|
1839
|
-
this.log('debug', `DM check failed after ${maxRetries} attempts: ${lastError.message}`);
|
|
1841
|
+
if (dashboardStarted) this.log('debug', `DM check failed after ${maxRetries} attempts: ${lastError.message}`);
|
|
1840
1842
|
return { deaths: 0, levelUps: 0, currentLevel: 0, lifesavers: -1 };
|
|
1841
1843
|
}
|
|
1842
1844
|
|
|
@@ -3646,12 +3648,12 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
3646
3648
|
parts.push(`${D}${pulse}♥?${c.reset}`);
|
|
3647
3649
|
}
|
|
3648
3650
|
if (parts.length > 0) {
|
|
3649
|
-
|
|
3651
|
+
recentLogs.push({ ts: Date.now(), username: w.username, color: w.color, command: 'dm check', response: parts.join(' '), status: 'ok' });
|
|
3650
3652
|
}
|
|
3651
3653
|
} catch {}
|
|
3652
3654
|
}
|
|
3653
3655
|
if (dmNoLs.length > 0) {
|
|
3654
|
-
|
|
3656
|
+
recentLogs.push({ ts: Date.now(), username: 'system', color: rgb(239, 68, 68), command: 'dm check', response: `⚠ No lifesavers: ${dmNoLs.join(', ')}`, status: 'warn' });
|
|
3655
3657
|
// Set Redis keys to block crime/search
|
|
3656
3658
|
for (const w of activeWorkers) {
|
|
3657
3659
|
if (dmNoLs.includes(w.username) && redis) {
|
|
@@ -3663,7 +3665,7 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
3663
3665
|
}
|
|
3664
3666
|
}
|
|
3665
3667
|
if (dmUnknown.length > 0) {
|
|
3666
|
-
|
|
3668
|
+
recentLogs.push({ ts: Date.now(), username: 'system', color: rgb(251, 191, 36), command: 'dm check', response: `⚠ Lifesavers unknown — live monitor: ${dmUnknown.join(', ')}`, status: 'warn' });
|
|
3667
3669
|
// Crime/search on these accounts will be skipped via safety hold until the live
|
|
3668
3670
|
// DM gateway listener detects a death (→ sets count) or confirms clean.
|
|
3669
3671
|
}
|
|
@@ -3671,7 +3673,7 @@ async function start(apiKey, apiUrl, opts = {}) {
|
|
|
3671
3673
|
if (dmDeaths > 0) dmSummaryParts.push(`${dmDeaths} deaths`);
|
|
3672
3674
|
if (dmLevelUps > 0) dmSummaryParts.push(`${dmLevelUps} level-ups`);
|
|
3673
3675
|
if (dmUnknown.length > 0) dmSummaryParts.push(`${dmUnknown.length} pending`);
|
|
3674
|
-
|
|
3676
|
+
recentLogs.push({ ts: Date.now(), username: 'system', color: rgb(52, 211, 153), command: 'dm check', response: dmSummaryParts.length > 0 ? dmSummaryParts.join(', ') : 'clean — no deaths or level-ups', status: 'ok' });
|
|
3675
3677
|
console.log('');
|
|
3676
3678
|
|
|
3677
3679
|
console.log(` ${rgb(139, 92, 246)}${c.bold}>>>${c.reset} ${gradientText('Starting grind loops...', [139, 92, 246], [52, 211, 153])}`);
|