dankgrinder 6.17.0 → 6.21.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/adventure.js +5 -5
- package/lib/commands/crime.js +9 -1
- package/lib/commands/postmemes.js +4 -4
- package/lib/commands/search.js +5 -2
- package/lib/commands/stream.js +7 -7
- package/lib/commands/utils.js +52 -35
- package/lib/grinder.js +420 -297
- package/lib/rawLogger.js +46 -8
- package/package.json +1 -1
|
@@ -64,7 +64,7 @@ async function clickAndRefetch(channel, msg, btn) {
|
|
|
64
64
|
LOG.error(`[adventure] Click error: ${e.message}`);
|
|
65
65
|
return null;
|
|
66
66
|
}
|
|
67
|
-
await sleep(
|
|
67
|
+
await sleep(100);
|
|
68
68
|
return await refetchMsg(channel, msg.id);
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -174,7 +174,7 @@ async function playAdventureRounds(channel, msg) {
|
|
|
174
174
|
const choice = pickSafeChoice(choices);
|
|
175
175
|
if (choice) {
|
|
176
176
|
LOG.info(`[adventure] → Choosing: "${choice.label}"`);
|
|
177
|
-
await sleep(
|
|
177
|
+
await sleep(50);
|
|
178
178
|
const afterChoice = await clickAndRefetch(channel, current, choice);
|
|
179
179
|
if (afterChoice) {
|
|
180
180
|
current = afterChoice;
|
|
@@ -208,7 +208,7 @@ async function playAdventureRounds(channel, msg) {
|
|
|
208
208
|
} else if (nextBtnNow && nextBtnNow.disabled) {
|
|
209
209
|
// Next is disabled but no choices found — might be loading
|
|
210
210
|
LOG.debug(`[adventure] Next disabled, no choices — waiting...`);
|
|
211
|
-
await sleep(
|
|
211
|
+
await sleep(150);
|
|
212
212
|
const refreshed = await refetchMsg(channel, current.id);
|
|
213
213
|
if (refreshed) {
|
|
214
214
|
current = refreshed;
|
|
@@ -221,7 +221,7 @@ async function playAdventureRounds(channel, msg) {
|
|
|
221
221
|
// No next button at all
|
|
222
222
|
LOG.debug(`[adventure] No Next button — checking if done`);
|
|
223
223
|
if (isAdventureDone(current)) break;
|
|
224
|
-
await sleep(
|
|
224
|
+
await sleep(200);
|
|
225
225
|
const refreshed = await refetchMsg(channel, current.id);
|
|
226
226
|
if (refreshed) {
|
|
227
227
|
current = refreshed;
|
|
@@ -374,7 +374,7 @@ async function runAdventure({ channel, waitForDankMemer, client }) {
|
|
|
374
374
|
} catch (e) {
|
|
375
375
|
LOG.error(`[adventure] Select error: ${e.message}`);
|
|
376
376
|
}
|
|
377
|
-
await sleep(
|
|
377
|
+
await sleep(150);
|
|
378
378
|
}
|
|
379
379
|
}
|
|
380
380
|
|
package/lib/commands/crime.js
CHANGED
|
@@ -16,11 +16,19 @@ const {
|
|
|
16
16
|
const { Trie, VoseAlias, LRUCache } = require('../structures');
|
|
17
17
|
|
|
18
18
|
const SAFE_CRIME_OPTIONS = Object.freeze([
|
|
19
|
-
|
|
19
|
+
// 100% safe (from logs analysis)
|
|
20
|
+
'identity theft', 'fraud', 'littering',
|
|
21
|
+
// 67% safe
|
|
22
|
+
'dui',
|
|
23
|
+
// Other potentially safe options
|
|
24
|
+
'tax evasion', 'cybercrime', 'hacking',
|
|
20
25
|
'money laundering', 'tax fraud', 'insurance fraud', 'scam',
|
|
21
26
|
]);
|
|
22
27
|
|
|
23
28
|
const RISKY_CRIME_OPTIONS = Object.freeze([
|
|
29
|
+
// 0% safe (from logs)
|
|
30
|
+
'cyber bullying', 'trespassing', 'shoplifting',
|
|
31
|
+
// Known dangerous
|
|
24
32
|
'murder', 'arson', 'assault', 'kidnap', 'terrorism',
|
|
25
33
|
]);
|
|
26
34
|
|
|
@@ -63,7 +63,7 @@ async function runPostMemes({ channel, waitForDankMemer }) {
|
|
|
63
63
|
if (initLower.includes('cannot post another meme') || initLower.includes('dead meme') ||
|
|
64
64
|
initLower.includes('another meme for another')) {
|
|
65
65
|
const minMatch = initText.match(RE_COOLDOWN_MIN);
|
|
66
|
-
const cdSec = minMatch ? parseInt(minMatch[1]) * 60 :
|
|
66
|
+
const cdSec = minMatch ? parseInt(minMatch[1]) * 60 : 150;
|
|
67
67
|
LOG.warn(`[pm] Cooldown: ${cdSec}s`);
|
|
68
68
|
return { result: `pm cooldown ${cdSec}s`, coins: 0, nextCooldownSec: cdSec };
|
|
69
69
|
}
|
|
@@ -110,7 +110,7 @@ async function runPostMemes({ channel, waitForDankMemer }) {
|
|
|
110
110
|
try {
|
|
111
111
|
await response.selectMenu(locRowIdx, [opt.value]);
|
|
112
112
|
} catch (e) { LOG.error(`[pm] Platform select error: ${e.message}`); }
|
|
113
|
-
await sleep(
|
|
113
|
+
await sleep(100);
|
|
114
114
|
const updated = await refetchMsg(channel, msgId);
|
|
115
115
|
if (updated) { response = updated; logMsg(response, 'pm-after-platform'); }
|
|
116
116
|
}
|
|
@@ -123,7 +123,7 @@ async function runPostMemes({ channel, waitForDankMemer }) {
|
|
|
123
123
|
try {
|
|
124
124
|
await response.selectMenu(kindRowIdx, [opt.value]);
|
|
125
125
|
} catch (e) { LOG.error(`[pm] Kind select error: ${e.message}`); }
|
|
126
|
-
await sleep(
|
|
126
|
+
await sleep(100);
|
|
127
127
|
const updated = await refetchMsg(channel, msgId);
|
|
128
128
|
if (updated) { response = updated; logMsg(response, 'pm-after-kind'); }
|
|
129
129
|
}
|
|
@@ -136,7 +136,7 @@ async function runPostMemes({ channel, waitForDankMemer }) {
|
|
|
136
136
|
LOG.info(`[pm] Clicking "${postBtn.label}"...`);
|
|
137
137
|
try {
|
|
138
138
|
await safeClickButton(response, postBtn);
|
|
139
|
-
await sleep(
|
|
139
|
+
await sleep(100);
|
|
140
140
|
const final = await refetchMsg(channel, msgId);
|
|
141
141
|
if (final) {
|
|
142
142
|
logMsg(final, 'pm-result');
|
package/lib/commands/search.js
CHANGED
|
@@ -16,9 +16,12 @@ const {
|
|
|
16
16
|
const { VoseAlias, Trie, EMA, LRUCache } = require('../structures');
|
|
17
17
|
|
|
18
18
|
const SAFE_SEARCH_LOCATIONS = Object.freeze([
|
|
19
|
+
// 100% safe (from logs analysis)
|
|
20
|
+
'shoe', 'washer', 'attic', 'pocket',
|
|
21
|
+
// Other safe locations
|
|
19
22
|
'sofa', 'mailbox', 'dog', 'car', 'dresser', 'laundromat', 'bed',
|
|
20
|
-
'couch', 'pantry', 'fridge', 'kitchen', 'bathroom',
|
|
21
|
-
'closet', '
|
|
23
|
+
'couch', 'pantry', 'fridge', 'kitchen', 'bathroom',
|
|
24
|
+
'closet', 'vacuum', 'toilet', 'sink', 'shower',
|
|
22
25
|
'tree', 'grass', 'bushes', 'garden', 'park', 'backyard',
|
|
23
26
|
]);
|
|
24
27
|
|
package/lib/commands/stream.js
CHANGED
|
@@ -230,10 +230,10 @@ async function runStream({ channel, waitForDankMemer, client }) {
|
|
|
230
230
|
for (const item of itemsToBuy) {
|
|
231
231
|
const bought = await buyItem({ channel, waitForDankMemer, client, itemName: item, quantity: 1 });
|
|
232
232
|
if (!bought) return { result: `need ${item} (buy failed)`, coins: 0, nextCooldownSec: 1800 };
|
|
233
|
-
await humanDelay(
|
|
233
|
+
await humanDelay(200, 400);
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
-
await sleep(
|
|
236
|
+
await sleep(800);
|
|
237
237
|
await channel.send('pls stream');
|
|
238
238
|
response = await waitForDankMemer(12000);
|
|
239
239
|
if (!response) return { result: 'no response after buy', coins: 0, nextCooldownSec: 180 };
|
|
@@ -256,7 +256,7 @@ async function runStream({ channel, waitForDankMemer, client }) {
|
|
|
256
256
|
|
|
257
257
|
const selected = await selectRandomStreamOption(response);
|
|
258
258
|
if (selected) {
|
|
259
|
-
await humanDelay(
|
|
259
|
+
await humanDelay(80, 180);
|
|
260
260
|
const updatedAfterSelect = (await waitForDankMemer(5000)) || (await refetchMsg(channel, response.id));
|
|
261
261
|
if (updatedAfterSelect) {
|
|
262
262
|
response = updatedAfterSelect;
|
|
@@ -294,7 +294,7 @@ async function runStream({ channel, waitForDankMemer, client }) {
|
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
-
await sleep(
|
|
297
|
+
await sleep(150);
|
|
298
298
|
const fresh = await refetchMsg(channel, response.id);
|
|
299
299
|
if (fresh) {
|
|
300
300
|
response = fresh;
|
|
@@ -305,7 +305,7 @@ async function runStream({ channel, waitForDankMemer, client }) {
|
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
LOG.info('[stream] Clicking "Go Live"');
|
|
308
|
-
await humanDelay(
|
|
308
|
+
await humanDelay(50, 120);
|
|
309
309
|
try {
|
|
310
310
|
const before = response;
|
|
311
311
|
const liveResult = await safeClickButton(response, goLiveBtn);
|
|
@@ -340,7 +340,7 @@ async function runStream({ channel, waitForDankMemer, client }) {
|
|
|
340
340
|
);
|
|
341
341
|
if (fallbackBtn) {
|
|
342
342
|
LOG.info('[stream] Go Live transition not detected; trying setup fallback');
|
|
343
|
-
await humanDelay(
|
|
343
|
+
await humanDelay(40, 100);
|
|
344
344
|
try {
|
|
345
345
|
const fallbackRes = await safeClickButton(response, fallbackBtn);
|
|
346
346
|
const afterFallback = fallbackRes || (await waitForStreamTransition({
|
|
@@ -376,7 +376,7 @@ async function runStream({ channel, waitForDankMemer, client }) {
|
|
|
376
376
|
const action = pickRandom(actions);
|
|
377
377
|
const actionAt = new Date();
|
|
378
378
|
LOG.info(`[stream] Live action: "${action.label}"`);
|
|
379
|
-
await humanDelay(
|
|
379
|
+
await humanDelay(60, 150);
|
|
380
380
|
try {
|
|
381
381
|
const clicked = await safeClickButton(response, action);
|
|
382
382
|
let updated = clicked || (await waitForDankMemer(6000)) || (await refetchMsg(channel, response.id));
|
package/lib/commands/utils.js
CHANGED
|
@@ -311,49 +311,66 @@ function findSelectMenuOption(msg, label) {
|
|
|
311
311
|
// Safe button click — tries library methods first, falls back to raw HTTP for CV2.
|
|
312
312
|
// When CV2 fallback is used, waits for the message to update so callers always
|
|
313
313
|
// get the updated message back (instead of null, which broke multi-round games).
|
|
314
|
-
async function safeClickButton(msg, button) {
|
|
314
|
+
async function safeClickButton(msg, button, retries = 2) {
|
|
315
315
|
// Skip LINK buttons (external URLs) — they have style=LINK/5 and no customId
|
|
316
316
|
if (button.style === 'LINK' || button.style === 5 || (!button.customId && !button.custom_id && typeof button.click !== 'function')) {
|
|
317
317
|
return null;
|
|
318
318
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
const id = button.customId || button.custom_id;
|
|
323
|
-
if (id && typeof msg.clickButton === 'function') {
|
|
319
|
+
|
|
320
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
324
321
|
try {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (interactionAck) msg._lastInteractionAck = interactionAck;
|
|
335
|
-
// Wait for Dank Memer to process the interaction and update the message
|
|
336
|
-
const updatedMsg = await new Promise((resolve) => {
|
|
337
|
-
const timeout = setTimeout(() => {
|
|
338
|
-
msg.client?.removeListener?.('messageUpdate', handler);
|
|
339
|
-
resolve(null);
|
|
340
|
-
}, 8000);
|
|
341
|
-
const handler = (_, newMsg) => {
|
|
342
|
-
if (newMsg.id === msg.id) {
|
|
343
|
-
clearTimeout(timeout);
|
|
344
|
-
msg.client?.removeListener?.('messageUpdate', handler);
|
|
345
|
-
resolve(newMsg);
|
|
322
|
+
if (typeof button.click === 'function') {
|
|
323
|
+
return await button.click();
|
|
324
|
+
}
|
|
325
|
+
const id = button.customId || button.custom_id;
|
|
326
|
+
if (id && typeof msg.clickButton === 'function') {
|
|
327
|
+
try {
|
|
328
|
+
return await msg.clickButton(id);
|
|
329
|
+
} catch {
|
|
330
|
+
// Fall through to CV2 raw interaction fallback.
|
|
346
331
|
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
332
|
+
}
|
|
333
|
+
// CV2 fallback: send interaction via raw HTTP, then wait for the message
|
|
334
|
+
// to update so we can return the updated message to the caller.
|
|
335
|
+
if (id) {
|
|
336
|
+
const interactionAck = await clickCV2Button(msg, id);
|
|
337
|
+
if (interactionAck) msg._lastInteractionAck = interactionAck;
|
|
338
|
+
// Wait for Dank Memer to process the interaction and update the message
|
|
339
|
+
const updatedMsg = await new Promise((resolve) => {
|
|
340
|
+
const timeout = setTimeout(() => {
|
|
341
|
+
msg.client?.removeListener?.('messageUpdate', handler);
|
|
342
|
+
resolve(null);
|
|
343
|
+
}, 6000);
|
|
344
|
+
const handler = (_, newMsg) => {
|
|
345
|
+
if (newMsg.id === msg.id) {
|
|
346
|
+
clearTimeout(timeout);
|
|
347
|
+
msg.client?.removeListener?.('messageUpdate', handler);
|
|
348
|
+
resolve(newMsg);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
msg.client?.on?.('messageUpdate', handler);
|
|
352
|
+
});
|
|
353
|
+
if (updatedMsg) {
|
|
354
|
+
await ensureCV2(updatedMsg);
|
|
355
|
+
return updatedMsg;
|
|
356
|
+
}
|
|
357
|
+
// Retry if we got null
|
|
358
|
+
if (attempt < retries) {
|
|
359
|
+
await new Promise(r => setTimeout(r, 300 + attempt * 200));
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
throw new Error('No click method available on button');
|
|
365
|
+
} catch (err) {
|
|
366
|
+
if (attempt < retries) {
|
|
367
|
+
await new Promise(r => setTimeout(r, 300 + attempt * 200));
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
throw err;
|
|
353
371
|
}
|
|
354
|
-
return null;
|
|
355
372
|
}
|
|
356
|
-
|
|
373
|
+
return null;
|
|
357
374
|
}
|
|
358
375
|
|
|
359
376
|
// ── Hold Tight Detection ─────────────────────────────────────
|