dankgrinder 5.14.0 → 5.19.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/farm.js +1540 -0
- package/lib/commands/farmVision.js +437 -0
- package/lib/commands/index.js +2 -0
- package/lib/commands/shop.js +221 -73
- package/lib/commands/stream.js +102 -15
- package/lib/commands/utils.js +98 -9
- package/lib/grinder.js +1 -0
- package/package.json +1 -1
package/lib/commands/utils.js
CHANGED
|
@@ -249,6 +249,17 @@ function flattenComponents(components) {
|
|
|
249
249
|
_accessoryOf: item,
|
|
250
250
|
});
|
|
251
251
|
}
|
|
252
|
+
if (acc.type === 3 || acc.type === 'SELECT_MENU' || acc.type === 'STRING_SELECT') {
|
|
253
|
+
flat.push({
|
|
254
|
+
type: 'STRING_SELECT',
|
|
255
|
+
customId: acc.custom_id || acc.customId,
|
|
256
|
+
options: acc.options || [],
|
|
257
|
+
disabled: acc.disabled || false,
|
|
258
|
+
placeholder: acc.placeholder,
|
|
259
|
+
data: acc,
|
|
260
|
+
_accessoryOf: item,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
252
263
|
}
|
|
253
264
|
}
|
|
254
265
|
return flat;
|
|
@@ -273,7 +284,7 @@ function findSelectMenuOption(msg, label) {
|
|
|
273
284
|
const menus = getAllSelectMenus(msg);
|
|
274
285
|
for (const comp of menus) {
|
|
275
286
|
const opt = (comp.options || []).find(o => o.label?.toLowerCase().includes(label.toLowerCase()));
|
|
276
|
-
if (opt) return { menuCustomId: comp.customId, option: opt, component: comp };
|
|
287
|
+
if (opt) return { menuCustomId: comp.customId || comp.custom_id, option: opt, component: comp };
|
|
277
288
|
}
|
|
278
289
|
return null;
|
|
279
290
|
}
|
|
@@ -300,7 +311,8 @@ async function safeClickButton(msg, button) {
|
|
|
300
311
|
// CV2 fallback: send interaction via raw HTTP, then wait for the message
|
|
301
312
|
// to update so we can return the updated message to the caller.
|
|
302
313
|
if (id) {
|
|
303
|
-
await clickCV2Button(msg, id);
|
|
314
|
+
const interactionAck = await clickCV2Button(msg, id);
|
|
315
|
+
if (interactionAck) msg._lastInteractionAck = interactionAck;
|
|
304
316
|
// Wait for Dank Memer to process the interaction and update the message
|
|
305
317
|
const updatedMsg = await new Promise((resolve) => {
|
|
306
318
|
const timeout = setTimeout(() => {
|
|
@@ -429,13 +441,15 @@ function isCV2(msg) {
|
|
|
429
441
|
|
|
430
442
|
async function ensureCV2(msg, force = false) {
|
|
431
443
|
if (!msg) return msg;
|
|
432
|
-
|
|
444
|
+
const msgEditedTs = msg.editedTimestamp || msg.editedAt?.getTime?.() || null;
|
|
445
|
+
if (!force && msg._cv2 && msg._cv2EditedTs === msgEditedTs) return msg;
|
|
433
446
|
if (!isCV2(msg)) return msg;
|
|
434
447
|
try {
|
|
435
448
|
if (force) {
|
|
436
449
|
delete msg._cv2;
|
|
437
450
|
delete msg._cv2text;
|
|
438
451
|
delete msg._cv2buttons;
|
|
452
|
+
delete msg._cv2EditedTs;
|
|
439
453
|
cv2Cache.delete(msg.id);
|
|
440
454
|
}
|
|
441
455
|
const token = msg.client?.token;
|
|
@@ -445,10 +459,17 @@ async function ensureCV2(msg, force = false) {
|
|
|
445
459
|
// LRU cache hit — O(1) lookup avoids redundant HTTP fetches
|
|
446
460
|
const cached = cv2Cache.get(msg.id);
|
|
447
461
|
if (cached && !force) {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
462
|
+
const cachedComponents = Array.isArray(cached) ? cached : cached.components;
|
|
463
|
+
const cachedEditedTs = Array.isArray(cached) ? null : (cached.editedTimestamp || null);
|
|
464
|
+
|
|
465
|
+
// If message has been edited since cache snapshot, ignore stale cache.
|
|
466
|
+
if (!msgEditedTs || cachedEditedTs === msgEditedTs) {
|
|
467
|
+
msg._cv2 = cachedComponents;
|
|
468
|
+
msg._cv2text = _extractCV2Text(cachedComponents).trim();
|
|
469
|
+
msg._cv2buttons = _extractCV2Buttons(cachedComponents);
|
|
470
|
+
msg._cv2EditedTs = cachedEditedTs;
|
|
471
|
+
return msg;
|
|
472
|
+
}
|
|
452
473
|
}
|
|
453
474
|
|
|
454
475
|
let raw = null;
|
|
@@ -470,10 +491,11 @@ async function ensureCV2(msg, force = false) {
|
|
|
470
491
|
}
|
|
471
492
|
|
|
472
493
|
if (raw?.components) {
|
|
473
|
-
cv2Cache.set(msg.id, raw.components);
|
|
494
|
+
cv2Cache.set(msg.id, { components: raw.components, editedTimestamp: msgEditedTs });
|
|
474
495
|
msg._cv2 = raw.components;
|
|
475
496
|
msg._cv2text = _extractCV2Text(raw.components).trim();
|
|
476
497
|
msg._cv2buttons = _extractCV2Buttons(raw.components);
|
|
498
|
+
msg._cv2EditedTs = msgEditedTs;
|
|
477
499
|
}
|
|
478
500
|
} catch (e) { LOG.debug(`[cv2] fetch error: ${e.message}`); }
|
|
479
501
|
return msg;
|
|
@@ -502,7 +524,73 @@ async function clickCV2Button(msg, customId) {
|
|
|
502
524
|
Authorization: token, 'Content-Type': 'application/json',
|
|
503
525
|
}, payload);
|
|
504
526
|
if (resp.status >= 400) throw new Error(`CV2 click ${resp.status}: ${resp.body.substring(0, 200)}`);
|
|
505
|
-
|
|
527
|
+
|
|
528
|
+
let parsed = null;
|
|
529
|
+
try {
|
|
530
|
+
parsed = resp.body ? JSON.parse(resp.body) : null;
|
|
531
|
+
} catch {
|
|
532
|
+
parsed = null;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const data = parsed?.data || null;
|
|
536
|
+
if (!data && !parsed) return null;
|
|
537
|
+
|
|
538
|
+
return {
|
|
539
|
+
interactionStatus: resp.status,
|
|
540
|
+
interactionType: parsed?.type ?? null,
|
|
541
|
+
flags: data?.flags ?? parsed?.flags ?? 0,
|
|
542
|
+
content: data?.content ?? parsed?.content ?? '',
|
|
543
|
+
embeds: data?.embeds ?? parsed?.embeds ?? [],
|
|
544
|
+
components: data?.components ?? parsed?.components ?? [],
|
|
545
|
+
raw: parsed || resp.body,
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
async function clickCV2SelectMenu(msg, customId, values = []) {
|
|
550
|
+
const token = msg.client?.token;
|
|
551
|
+
const chId = msg.channelId || msg.channel?.id;
|
|
552
|
+
const gId = msg.guildId || msg.guild?.id;
|
|
553
|
+
if (!token) throw new Error('No token for CV2 select');
|
|
554
|
+
const sessionId = msg.client?.ws?.shards?.first?.()?.sessionId;
|
|
555
|
+
const nonce = `${BigInt(Date.now() - 1420070400000) << 22n}`;
|
|
556
|
+
const payloadObj = {
|
|
557
|
+
type: 3,
|
|
558
|
+
application_id: String(msg.applicationId || DANK_MEMER_ID),
|
|
559
|
+
nonce,
|
|
560
|
+
channel_id: String(chId),
|
|
561
|
+
message_id: String(msg.id),
|
|
562
|
+
data: {
|
|
563
|
+
component_type: 3,
|
|
564
|
+
custom_id: customId,
|
|
565
|
+
values: Array.isArray(values) ? values.map(v => String(v)) : [],
|
|
566
|
+
},
|
|
567
|
+
};
|
|
568
|
+
if (gId) payloadObj.guild_id = String(gId);
|
|
569
|
+
if (sessionId) payloadObj.session_id = sessionId;
|
|
570
|
+
|
|
571
|
+
const resp = await _httpPost('https://discord.com/api/v9/interactions', {
|
|
572
|
+
Authorization: token, 'Content-Type': 'application/json',
|
|
573
|
+
}, JSON.stringify(payloadObj));
|
|
574
|
+
if (resp.status >= 400) throw new Error(`CV2 select ${resp.status}: ${resp.body.substring(0, 200)}`);
|
|
575
|
+
|
|
576
|
+
let parsed = null;
|
|
577
|
+
try {
|
|
578
|
+
parsed = resp.body ? JSON.parse(resp.body) : null;
|
|
579
|
+
} catch {
|
|
580
|
+
parsed = null;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const data = parsed?.data || null;
|
|
584
|
+
if (!data && !parsed) return null;
|
|
585
|
+
return {
|
|
586
|
+
interactionStatus: resp.status,
|
|
587
|
+
interactionType: parsed?.type ?? null,
|
|
588
|
+
flags: data?.flags ?? parsed?.flags ?? 0,
|
|
589
|
+
content: data?.content ?? parsed?.content ?? '',
|
|
590
|
+
embeds: data?.embeds ?? parsed?.embeds ?? [],
|
|
591
|
+
components: data?.components ?? parsed?.components ?? [],
|
|
592
|
+
raw: parsed || resp.body,
|
|
593
|
+
};
|
|
506
594
|
}
|
|
507
595
|
|
|
508
596
|
// ── Item Detection (Aho-Corasick Automaton) ──────────────────
|
|
@@ -575,6 +663,7 @@ module.exports = {
|
|
|
575
663
|
isCV2,
|
|
576
664
|
ensureCV2,
|
|
577
665
|
clickCV2Button,
|
|
666
|
+
clickCV2SelectMenu,
|
|
578
667
|
// Shared structures and optimized constants
|
|
579
668
|
strings,
|
|
580
669
|
cv2Cache,
|
package/lib/grinder.js
CHANGED
|
@@ -1353,6 +1353,7 @@ class AccountWorker {
|
|
|
1353
1353
|
case 'search': cmdResult = await commands.runSearch(cmdOpts); break;
|
|
1354
1354
|
case 'crime': cmdResult = await commands.runCrime(cmdOpts); break;
|
|
1355
1355
|
case 'hl': cmdResult = await commands.runHighLow(cmdOpts); break;
|
|
1356
|
+
case 'farm': cmdResult = await commands.runFarm(cmdOpts); break;
|
|
1356
1357
|
case 'pm': cmdResult = await commands.runPostMemes(cmdOpts); break;
|
|
1357
1358
|
case 'hunt': cmdResult = await commands.runHunt(cmdOpts); break;
|
|
1358
1359
|
case 'dig': cmdResult = await commands.runDig(cmdOpts); break;
|