@vanzxy/baileys 1.5.9 → 1.6.1
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.
Potentially problematic release.
This version of @vanzxy/baileys might be problematic. Click here for more details.
- package/WAProto/index.js +59524 -33708
- package/lib/Utils/MessageBuilder.js +198 -64
- package/lib/Utils/MessageBuilder_d.ts +5 -2
- package/lib/Utils/process-message.js +47 -1
- package/package.json +1 -1
|
@@ -696,6 +696,58 @@ class Button extends BaseBuilder {
|
|
|
696
696
|
return this;
|
|
697
697
|
}
|
|
698
698
|
|
|
699
|
+
// Vanz@Add 26-08-26 --- setBloksWidget(): Meta's Bloks/A2UI format, a sibling field to
|
|
700
|
+
// nativeFlowMessage on interactiveMessage (NOT part of the AIRich rich-response system —
|
|
701
|
+
// this is a real native interactive UI: checkboxes/text fields/buttons actually work).
|
|
702
|
+
// Captured traffic gives the A2UI payload as a flat `components` array where every node has
|
|
703
|
+
// an `id` and children/child reference OTHER nodes by id string. Authoring that by hand is
|
|
704
|
+
// error-prone (dangling ids, ordering), so this accepts a plain nested tree instead —
|
|
705
|
+
// { component, ...props, children: [...] } / { component, ...props, child: {...} } — and
|
|
706
|
+
// flattens it into that array itself, auto-assigning ids.
|
|
707
|
+
#flattenBloks(tree, out, counter = { n: 0 }, id = 'root') {
|
|
708
|
+
if (!tree || typeof tree !== 'object') throw new TypeError('setBloksWidget: every node needs a "component" type');
|
|
709
|
+
const { component, children, child, ...props } = tree;
|
|
710
|
+
if (typeof component !== 'string' || !component) throw new TypeError('setBloksWidget: every node needs a "component" type');
|
|
711
|
+
|
|
712
|
+
const node = { id, component, ...props };
|
|
713
|
+
|
|
714
|
+
if (Array.isArray(children)) {
|
|
715
|
+
node.children = children.map((c) => this.#flattenBloks(c, out, counter, `n${counter.n++}`));
|
|
716
|
+
} else if (child) {
|
|
717
|
+
node.child = this.#flattenBloks(child, out, counter, `n${counter.n++}`);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
out.push(node);
|
|
721
|
+
return id;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Set a Bloks/A2UI native widget (`bloksWidget`, `type: "im_a2ui"`) — a real interactive
|
|
726
|
+
* screen (images, video, checkboxes, text fields, buttons that fire an `action`), not a
|
|
727
|
+
* static card. Pass a nested tree; ids are assigned automatically.
|
|
728
|
+
* @param {Record<string, any>} tree Root node, e.g. `{ component: 'Column', children: [...] }`.
|
|
729
|
+
* @param {{uuid?: string, catalogId?: string, surfaceId?: string, version?: string}} [options]
|
|
730
|
+
*/
|
|
731
|
+
setBloksWidget(tree, { uuid = crypto.randomUUID(), catalogId = 'https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json', surfaceId, version = 'v0.9' } = {}) {
|
|
732
|
+
const components = [];
|
|
733
|
+
this.#flattenBloks(tree, components);
|
|
734
|
+
|
|
735
|
+
this._bloksWidget = {
|
|
736
|
+
uuid,
|
|
737
|
+
data: JSON.stringify({
|
|
738
|
+
version,
|
|
739
|
+
createSurface: {
|
|
740
|
+
surfaceId: surfaceId ?? `starcore-widget=${uuid}`,
|
|
741
|
+
catalogId,
|
|
742
|
+
components,
|
|
743
|
+
},
|
|
744
|
+
}),
|
|
745
|
+
type: 'im_a2ui',
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
return this;
|
|
749
|
+
}
|
|
750
|
+
|
|
699
751
|
/**
|
|
700
752
|
* Low-level escape hatch: push a raw native-flow button by name. Prefer the
|
|
701
753
|
* dedicated `add*()` helpers below when one exists — they validate the
|
|
@@ -1290,22 +1342,26 @@ class Button extends BaseBuilder {
|
|
|
1290
1342
|
|
|
1291
1343
|
/** @returns {Record<string, any>} The final content object, without generating/wrapping a WAMessage. Useful when composing this interactive card into something else (e.g. Carousel). */
|
|
1292
1344
|
async build(jid, { ...options } = {}) {
|
|
1293
|
-
if (this._buttons.length === 0) {
|
|
1294
|
-
throw new Error('Button requires at least one button (use addReply/addUrl/addCall/addSelection/addButton/...)');
|
|
1345
|
+
if (this._buttons.length === 0 && !this._bloksWidget) {
|
|
1346
|
+
throw new Error('Button requires at least one button (use addReply/addUrl/addCall/addSelection/addButton/...) or a Bloks widget (setBloksWidget())');
|
|
1295
1347
|
}
|
|
1296
1348
|
|
|
1297
|
-
if (this.#isLoneSingleSelect()) {
|
|
1349
|
+
if (this._buttons.length > 0 && this.#isLoneSingleSelect()) {
|
|
1298
1350
|
return generateWAMessageFromContent(jid, { ...this._extraPayload, ...this.#toListMessage() }, { ...options });
|
|
1299
1351
|
}
|
|
1300
1352
|
|
|
1301
|
-
const message = await this.toCard();
|
|
1353
|
+
const message = this._buttons.length > 0 ? await this.toCard() : {};
|
|
1302
1354
|
|
|
1303
1355
|
return generateWAMessageFromContent(
|
|
1304
1356
|
jid,
|
|
1305
1357
|
{
|
|
1358
|
+
...(this._bloksWidget && {
|
|
1359
|
+
messageContextInfo: { messageSecret: crypto.randomBytes(32) },
|
|
1360
|
+
}),
|
|
1306
1361
|
...this._extraPayload,
|
|
1307
1362
|
interactiveMessage: {
|
|
1308
1363
|
...message,
|
|
1364
|
+
...(this._bloksWidget && { bloksWidget: this._bloksWidget }),
|
|
1309
1365
|
contextInfo: this._contextInfo,
|
|
1310
1366
|
},
|
|
1311
1367
|
},
|
|
@@ -1328,12 +1384,25 @@ class Button extends BaseBuilder {
|
|
|
1328
1384
|
const bizContent = this.#isLoneSingleSelect()
|
|
1329
1385
|
? [{ tag: 'list', attrs: { v: '2', type: 'product_list' } }]
|
|
1330
1386
|
: [
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1387
|
+
...(this._buttons.length > 0
|
|
1388
|
+
? [
|
|
1389
|
+
{
|
|
1390
|
+
tag: 'interactive',
|
|
1391
|
+
attrs: { type: 'native_flow', v: '1' },
|
|
1392
|
+
content: [this.#buildNativeFlowNode()],
|
|
1393
|
+
},
|
|
1394
|
+
]
|
|
1395
|
+
: []),
|
|
1396
|
+
...(this._bloksWidget
|
|
1397
|
+
? [
|
|
1398
|
+
{
|
|
1399
|
+
tag: 'quality_control',
|
|
1400
|
+
attrs: { decision_id: crypto.randomUUID().replace(/-/g, ''), source_type: 'third_party' },
|
|
1401
|
+
content: [{ tag: 'decision_source', attrs: { value: 'df' } }],
|
|
1402
|
+
},
|
|
1403
|
+
]
|
|
1404
|
+
: []),
|
|
1405
|
+
];
|
|
1337
1406
|
|
|
1338
1407
|
await this.#client.relayMessage(msg.key.remoteJid, msg.message, {
|
|
1339
1408
|
messageId: msg.key.id,
|
|
@@ -1776,9 +1845,10 @@ class AIRich extends BaseBuilder {
|
|
|
1776
1845
|
}
|
|
1777
1846
|
|
|
1778
1847
|
return (...args) => {
|
|
1779
|
-
const opts = args.find((a) => a && typeof a === 'object' && !Array.isArray(a) && !Buffer.isBuffer(a) && ('id' in a || 'insertAt' in a));
|
|
1848
|
+
const opts = args.find((a) => a && typeof a === 'object' && !Array.isArray(a) && !Buffer.isBuffer(a) && ('id' in a || 'insertAt' in a || 'replace' in a));
|
|
1780
1849
|
const id = opts?.id;
|
|
1781
1850
|
const insertAt = opts?.insertAt;
|
|
1851
|
+
const replace = opts?.replace;
|
|
1782
1852
|
|
|
1783
1853
|
const subBefore = target._submessages.length;
|
|
1784
1854
|
const secBefore = target._sections.length;
|
|
@@ -1810,6 +1880,31 @@ class AIRich extends BaseBuilder {
|
|
|
1810
1880
|
const lastSec = anchor.secItems[anchor.secItems.length - 1];
|
|
1811
1881
|
const secIdx = lastSec ? target._sections.indexOf(lastSec) + 1 : target._sections.length;
|
|
1812
1882
|
target._sections.splice(secIdx, 0, ...secItems);
|
|
1883
|
+
} else if (replace) {
|
|
1884
|
+
// replace: delete the old block's items at their current positions,
|
|
1885
|
+
// then insert new items at the same positions
|
|
1886
|
+
const old = target._blocks.get(replace);
|
|
1887
|
+
if (!old) throw new Error(`replace: no block registered with id "${replace}" (register it first with { id: "${replace}" })`);
|
|
1888
|
+
|
|
1889
|
+
let subIdx = old.subItems.length > 0 ? target._submessages.indexOf(old.subItems[0]) : target._submessages.length;
|
|
1890
|
+
if (subIdx === -1) subIdx = target._submessages.length;
|
|
1891
|
+
for (const item of old.subItems) {
|
|
1892
|
+
const i = target._submessages.indexOf(item);
|
|
1893
|
+
if (i !== -1) target._submessages.splice(i, 1);
|
|
1894
|
+
}
|
|
1895
|
+
target._submessages.splice(subIdx, 0, ...subItems);
|
|
1896
|
+
|
|
1897
|
+
let secIdx = old.secItems.length > 0 ? target._sections.indexOf(old.secItems[0]) : target._sections.length;
|
|
1898
|
+
if (secIdx === -1) secIdx = target._sections.length;
|
|
1899
|
+
for (const item of old.secItems) {
|
|
1900
|
+
const i = target._sections.indexOf(item);
|
|
1901
|
+
if (i !== -1) target._sections.splice(i, 1);
|
|
1902
|
+
}
|
|
1903
|
+
target._sections.splice(secIdx, 0, ...secItems);
|
|
1904
|
+
|
|
1905
|
+
target._blocks.delete(replace);
|
|
1906
|
+
if (id) target._blocks.set(id, { subItems, secItems });
|
|
1907
|
+
else target._blocks.set(replace, { subItems, secItems });
|
|
1813
1908
|
} else {
|
|
1814
1909
|
target._submessages.push(...subItems);
|
|
1815
1910
|
target._sections.push(...secItems);
|
|
@@ -2014,21 +2109,38 @@ class AIRich extends BaseBuilder {
|
|
|
2014
2109
|
}
|
|
2015
2110
|
|
|
2016
2111
|
addSource(sources = [], { resolveUrl = false } = {}) {
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2112
|
+
// Accept 3 formats:
|
|
2113
|
+
// 1. Array of objects: [{ icon, url, title, subtitle }] — from v4.7 example
|
|
2114
|
+
// 2. Array of string arrays: [['iconUrl', 'url', 'text']]
|
|
2115
|
+
// 3. Single string array (shorthand for format 2): ['iconUrl', 'url', 'text']
|
|
2116
|
+
const isObjArray = Array.isArray(sources) && sources.every((item) => item && typeof item === 'object' && !Array.isArray(item));
|
|
2117
|
+
const isStrArrayArray = Array.isArray(sources) && sources.every((item) => Array.isArray(item) && item.every((v) => typeof v === 'string'));
|
|
2118
|
+
const isFlatStrArray = Array.isArray(sources) && sources.every((item) => typeof item === 'string');
|
|
2119
|
+
|
|
2120
|
+
if (!isObjArray && !isStrArrayArray && !isFlatStrArray) {
|
|
2121
|
+
throw new TypeError('addSource(): pass an array of objects { icon, url, title, subtitle } or string arrays [iconUrl, url, text]');
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
let normalized;
|
|
2125
|
+
if (isObjArray) {
|
|
2126
|
+
normalized = sources.map((item) => ({
|
|
2127
|
+
icon: item.icon ?? item.iconUrl ?? item.favicon ?? '',
|
|
2128
|
+
url: item.url ?? '',
|
|
2129
|
+
text: item.title ?? item.displayName ?? item.text ?? '',
|
|
2130
|
+
subtitle: item.subtitle ?? 'AI',
|
|
2131
|
+
}));
|
|
2132
|
+
} else {
|
|
2133
|
+
const arr = isFlatStrArray ? [sources] : sources;
|
|
2134
|
+
normalized = arr.map(([icon = '', url = '', text = '']) => ({ icon, url, text, subtitle: 'AI' }));
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
const source = normalized.map(({ icon, url, text, subtitle }) => ({
|
|
2026
2138
|
source_type: 'THIRD_PARTY',
|
|
2027
|
-
source_display_name: text
|
|
2028
|
-
source_subtitle:
|
|
2029
|
-
source_url: url
|
|
2139
|
+
source_display_name: text,
|
|
2140
|
+
source_subtitle: subtitle,
|
|
2141
|
+
source_url: url,
|
|
2030
2142
|
favicon: {
|
|
2031
|
-
url: Toolkit.resolveMedia(this.#client, icon
|
|
2143
|
+
url: Toolkit.resolveMedia(this.#client, icon, 'image', { resolveUrl }),
|
|
2032
2144
|
mime_type: 'image/jpeg',
|
|
2033
2145
|
width: 16,
|
|
2034
2146
|
height: 16,
|
|
@@ -2456,6 +2568,49 @@ class AIRich extends BaseBuilder {
|
|
|
2456
2568
|
return this;
|
|
2457
2569
|
}
|
|
2458
2570
|
|
|
2571
|
+
// Vanz@Add 25-08-26 --- ported from temen's MessageBuilderV4.7 (hasId/getIds/peek/delete).
|
|
2572
|
+
// That fork tracked every block in a unified `_nodes` array so query/delete-by-id was free;
|
|
2573
|
+
// this fork instead tracks blocks in the `_blocks` Map (id -> {subItems, secItems}, populated
|
|
2574
|
+
// by the constructor's Proxy on every add*/set* call that passes {id}) but never exposed a way
|
|
2575
|
+
// to query or undo one after the fact — you could insertAt an id but never inspect, check, or
|
|
2576
|
+
// remove it. These 4 read/delete that same Map, so no changes to the Proxy itself were needed.
|
|
2577
|
+
|
|
2578
|
+
/** Check whether a block id was registered by an earlier `add*()`/`set*()` call passing `{id}`. */
|
|
2579
|
+
hasId(id) {
|
|
2580
|
+
return typeof id === 'string' && this._blocks.has(id);
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
/** List every block id registered so far, in no particular order. */
|
|
2584
|
+
getIds() {
|
|
2585
|
+
return [...this._blocks.keys()];
|
|
2586
|
+
}
|
|
2587
|
+
|
|
2588
|
+
/** Inspect a registered block without modifying it. Returns `null` if `id` isn't registered. */
|
|
2589
|
+
peek(id) {
|
|
2590
|
+
const block = this._blocks.get(id);
|
|
2591
|
+
if (!block) return null;
|
|
2592
|
+
|
|
2593
|
+
return { id, sections: [...block.secItems], submessages: [...block.subItems] };
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
/** Remove a previously-added block (by the `id` passed to its `add*()`/`set*()` call) from the message. Throws if `id` isn't registered. */
|
|
2597
|
+
delete(id) {
|
|
2598
|
+
const block = this._blocks.get(id);
|
|
2599
|
+
if (!block) throw new Error(`delete(id): no block registered with id "${id}"`);
|
|
2600
|
+
|
|
2601
|
+
for (const item of block.subItems) {
|
|
2602
|
+
const idx = this._submessages.indexOf(item);
|
|
2603
|
+
if (idx !== -1) this._submessages.splice(idx, 1);
|
|
2604
|
+
}
|
|
2605
|
+
for (const item of block.secItems) {
|
|
2606
|
+
const idx = this._sections.indexOf(item);
|
|
2607
|
+
if (idx !== -1) this._sections.splice(idx, 1);
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2610
|
+
this._blocks.delete(id);
|
|
2611
|
+
return this;
|
|
2612
|
+
}
|
|
2613
|
+
|
|
2459
2614
|
/** Add a small metadata-style text line (`GenAIMetadataTextPrimitive`) — same visual style as the auto-appended footer/`addTip()`'s callout, but insertable anywhere and without `addTip()`'s icon prefix. */
|
|
2460
2615
|
addMetadata(text) {
|
|
2461
2616
|
if (typeof text !== 'string' || !text) throw new TypeError('addMetadata(text) requires a non-empty string');
|
|
@@ -2496,11 +2651,14 @@ class AIRich extends BaseBuilder {
|
|
|
2496
2651
|
return this;
|
|
2497
2652
|
}
|
|
2498
2653
|
|
|
2499
|
-
// Vanz@Add 22-08-26 (v4.7) --- addHeading/
|
|
2654
|
+
// Vanz@Add 22-08-26 (v4.7) --- addHeading/addWidget/addFooterAction: 3 primitives
|
|
2500
2655
|
// reverse-engineered from captured Meta-AI-in-WhatsApp traffic that this project's own crm/snip
|
|
2501
2656
|
// tooling (see rich-message-utils.js) dumps for study. Not in any public Baileys schema, so
|
|
2502
2657
|
// unknown enum values (kind/state on addWidget's ctas) are passed through as observed rather
|
|
2503
2658
|
// than guessed at, and documented as experimental below.
|
|
2659
|
+
// Vanz@Fix 25-08-26 --- removed addImageCard(): its GenAIImagePrimitive/preview_image+full_image
|
|
2660
|
+
// shape was mis-reverse-engineered (not a real WA schema) and crashed the client renderer on
|
|
2661
|
+
// arrival. addImage() already covers static image cards correctly — use that instead.
|
|
2504
2662
|
|
|
2505
2663
|
/** Add a large heading-style text block (`FOATextPrimitive`) — visually distinct from `addText()`'s regular paragraph text. */
|
|
2506
2664
|
addHeading(text) {
|
|
@@ -2523,39 +2681,6 @@ class AIRich extends BaseBuilder {
|
|
|
2523
2681
|
return this;
|
|
2524
2682
|
}
|
|
2525
2683
|
|
|
2526
|
-
/**
|
|
2527
|
-
* Add a "ready" static image card (`GenAIImagePrimitive`: preview + full-res, no generating/status
|
|
2528
|
-
* state) — distinct from `addImage()`'s AI-generation-style `GenAIImaginePrimitive`.
|
|
2529
|
-
* @param {string|Buffer} previewUrl Preview/thumbnail image.
|
|
2530
|
-
* @param {string|Buffer} [fullUrl] Full-resolution image; defaults to `previewUrl`.
|
|
2531
|
-
*/
|
|
2532
|
-
addImageCard(previewUrl, fullUrl = previewUrl, { resolveUrl = false } = {}) {
|
|
2533
|
-
if (!(typeof previewUrl === 'string' || Buffer.isBuffer(previewUrl))) {
|
|
2534
|
-
throw new TypeError('addImageCard(previewUrl) requires a string url or buffer');
|
|
2535
|
-
}
|
|
2536
|
-
|
|
2537
|
-
const preview = Toolkit.resolveMedia(this.#client, previewUrl, 'image', { resolveUrl });
|
|
2538
|
-
const full = fullUrl === previewUrl ? preview : Toolkit.resolveMedia(this.#client, fullUrl, 'image', { resolveUrl });
|
|
2539
|
-
|
|
2540
|
-
this._submessages.push({
|
|
2541
|
-
messageType: 1,
|
|
2542
|
-
gridImageMetadata: {
|
|
2543
|
-
gridImageUrl: { imagePreviewUrl: preview },
|
|
2544
|
-
imageUrls: [{ imagePreviewUrl: preview, imageHighResUrl: full, sourceUrl: full }],
|
|
2545
|
-
},
|
|
2546
|
-
});
|
|
2547
|
-
|
|
2548
|
-
this._sections.push(
|
|
2549
|
-
AIRich.newLayout('Single', {
|
|
2550
|
-
preview_image: { url: preview, mime_type: 'image/jpeg', __typename: 'GenAIMediaItem' },
|
|
2551
|
-
full_image: { url: full, mime_type: 'image/jpeg', __typename: 'GenAIMediaItem' },
|
|
2552
|
-
__typename: 'GenAIImagePrimitive',
|
|
2553
|
-
})
|
|
2554
|
-
);
|
|
2555
|
-
|
|
2556
|
-
return this;
|
|
2557
|
-
}
|
|
2558
|
-
|
|
2559
2684
|
/**
|
|
2560
2685
|
* Add a "3P extension" widget card (`GenAI3PExtWidgetPrimitive`) — a small panel with a title and
|
|
2561
2686
|
* a row of tappable CTA chips. Per captured traffic these CTAs call back into a tool (`tool_call_id`)
|
|
@@ -2574,8 +2699,10 @@ class AIRich extends BaseBuilder {
|
|
|
2574
2699
|
const items = Array.isArray(data) ? data : [data];
|
|
2575
2700
|
|
|
2576
2701
|
items.forEach((item, i) => {
|
|
2577
|
-
|
|
2578
|
-
|
|
2702
|
+
// header.title or top-level title required
|
|
2703
|
+
const hasTitle = item?.title || item?.header?.title;
|
|
2704
|
+
if (!hasTitle) {
|
|
2705
|
+
throw new TypeError(`addWidget() item[${i}] is missing a required "title" (or "header.title")`);
|
|
2579
2706
|
}
|
|
2580
2707
|
const ctas = item.ctas ?? item.actions;
|
|
2581
2708
|
if (!Array.isArray(ctas) || !ctas.length) {
|
|
@@ -2585,22 +2712,29 @@ class AIRich extends BaseBuilder {
|
|
|
2585
2712
|
|
|
2586
2713
|
this._submessages.push({
|
|
2587
2714
|
messageType: 2,
|
|
2588
|
-
messageText: items.map((item) => item.title).join(', '),
|
|
2715
|
+
messageText: items.map((item) => item.header?.title ?? item.title).join(', '),
|
|
2589
2716
|
});
|
|
2590
2717
|
|
|
2591
2718
|
const widgets = items.map((item) => {
|
|
2592
2719
|
const ctas = item.ctas ?? item.actions;
|
|
2720
|
+
// header accepts either a string title (legacy) or an object { title, subtitle }
|
|
2721
|
+
const headerTitle = item.header?.title ?? item.title;
|
|
2722
|
+
const headerSubtitle = item.header?.subtitle ?? item.subtitle ?? undefined;
|
|
2593
2723
|
return {
|
|
2594
|
-
header: {
|
|
2724
|
+
header: {
|
|
2725
|
+
title: headerTitle,
|
|
2726
|
+
...(headerSubtitle !== undefined && { subtitle: headerSubtitle }),
|
|
2727
|
+
__typename: 'GenAI3PExtWidgetStandardHeader',
|
|
2728
|
+
},
|
|
2595
2729
|
body: {
|
|
2596
2730
|
sections: item.sections ?? [],
|
|
2597
2731
|
ctas: ctas.map((cta, idx) => ({
|
|
2598
2732
|
label: cta.label ?? '',
|
|
2599
2733
|
state: cta.state ?? 'PENDING',
|
|
2600
2734
|
kind: cta.kind ?? 'OTHER',
|
|
2601
|
-
tool_call_id: cta.tool_call_id ?? String(idx).padStart(2, '0'),
|
|
2735
|
+
tool_call_id: cta.tool_call_id ?? cta.id ?? String(idx).padStart(2, '0'),
|
|
2602
2736
|
...(cta.toast !== false && {
|
|
2603
|
-
toast: { label: typeof cta.toast === 'string' ? cta.toast :
|
|
2737
|
+
toast: { label: typeof cta.toast === 'string' ? cta.toast : headerTitle, __typename: 'GenAI3PExtWidgetToast' },
|
|
2604
2738
|
}),
|
|
2605
2739
|
__typename: 'GenAI3PExtWidgetCTA',
|
|
2606
2740
|
})),
|
|
@@ -45,6 +45,7 @@ export class Button extends BaseBuilder {
|
|
|
45
45
|
setMedia(obj: Record<string, any>): this;
|
|
46
46
|
clearButtons(): this;
|
|
47
47
|
setParams(obj: Record<string, any>): this;
|
|
48
|
+
setBloksWidget(tree: Record<string, any>, options?: { uuid?: string; catalogId?: string; surfaceId?: string; version?: string }): this;
|
|
48
49
|
addButton(name: string, params: string | Record<string, any>): this;
|
|
49
50
|
makeRow(header?: string, title?: string, description?: string, id?: string): this;
|
|
50
51
|
makeSection(title?: string, highlight_label?: string): this;
|
|
@@ -178,10 +179,12 @@ export class AIRich extends BaseBuilder {
|
|
|
178
179
|
refreshResponseId(): this;
|
|
179
180
|
setBotResponseId(id: string): this;
|
|
180
181
|
refreshBotResponseId(): this;
|
|
182
|
+
hasId(id: string): boolean;
|
|
183
|
+
getIds(): string[];
|
|
184
|
+
peek(id: string): { id: string; sections: any[]; submessages: any[] } | null;
|
|
185
|
+
delete(id: string): this;
|
|
181
186
|
/** FOATextPrimitive — large heading text, distinct from addText()'s paragraph text. */
|
|
182
187
|
addHeading(text: string): this;
|
|
183
|
-
/** GenAIImagePrimitive — "ready" static image (preview + full-res), distinct from addImage()'s generation-style card. */
|
|
184
|
-
addImageCard(previewUrl: string | Buffer, fullUrl?: string | Buffer, options?: { resolveUrl?: boolean }): this;
|
|
185
188
|
/** GenAI3PExtWidgetPrimitive — experimental, reverse-engineered; see JSDoc in the .js file for caveats. */
|
|
186
189
|
addWidget(data: Record<string, any> | Record<string, any>[], options?: { layout?: 'Single' | 'HScroll' | 'ActionRow' | string }): this;
|
|
187
190
|
/** GenAIFooterActionPrimitive — footer action link chips (e.g. "Join our Group"). */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { Reader } from 'protobufjs/minimal.js';
|
|
2
3
|
import { proto } from '../../WAProto/index.js';
|
|
3
4
|
import { WAMessageStubType } from '../Types/index.js';
|
|
4
5
|
import { getContentType, normalizeMessageContent } from '../Utils/messages.js';
|
|
@@ -14,6 +15,51 @@ const REAL_MSG_STUB_TYPES = new Set([
|
|
|
14
15
|
WAMessageStubType.CALL_MISSED_VOICE
|
|
15
16
|
]);
|
|
16
17
|
const REAL_MSG_REQ_ME_STUB_TYPES = new Set([WAMessageStubType.GROUP_PARTICIPANT_ADD]);
|
|
18
|
+
// Vanz@Fix 26-08-26 --- the 26-08-26 WAProto refresh dropped `LIDMigrationMappingSyncPayload`
|
|
19
|
+
// / `LIDMigrationMapping` from the published schema; only the opaque envelope
|
|
20
|
+
// `LIDMigrationMappingSyncMessage { encodedMappingPayload: bytes }` is generated now.
|
|
21
|
+
// Nothing suggests the *inner* wire layout actually changed (WA's extractor just stopped
|
|
22
|
+
// walking this nested message), so we decode it by hand instead of guessing a new shape.
|
|
23
|
+
// TODO: verify against live traffic on the next audit pass — if Meta did change the inner
|
|
24
|
+
// layout this will start throwing and LID/PN pairs will silently stop syncing.
|
|
25
|
+
function decodeLidMigrationMappingSyncPayload(buf) {
|
|
26
|
+
const r = Reader.create(buf);
|
|
27
|
+
const out = { pnToLidMappings: [], chatDbMigrationTimestamp: undefined };
|
|
28
|
+
while (r.pos < r.len) {
|
|
29
|
+
const tag = r.uint32();
|
|
30
|
+
switch (tag >>> 3) {
|
|
31
|
+
case 1: {
|
|
32
|
+
const len = r.uint32();
|
|
33
|
+
const end = r.pos + len;
|
|
34
|
+
const entry = { pn: undefined, assignedLid: undefined, latestLid: undefined };
|
|
35
|
+
while (r.pos < end) {
|
|
36
|
+
const t2 = r.uint32();
|
|
37
|
+
switch (t2 >>> 3) {
|
|
38
|
+
case 1:
|
|
39
|
+
entry.pn = r.uint64();
|
|
40
|
+
break;
|
|
41
|
+
case 2:
|
|
42
|
+
entry.assignedLid = r.uint64();
|
|
43
|
+
break;
|
|
44
|
+
case 3:
|
|
45
|
+
entry.latestLid = r.uint64();
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
r.skipType(t2 & 7);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
out.pnToLidMappings.push(entry);
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 2:
|
|
55
|
+
out.chatDbMigrationTimestamp = r.uint64();
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
r.skipType(tag & 7);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
17
63
|
async function storeTcTokensFromHistorySync(chats, signalRepository, keyStore, logger) {
|
|
18
64
|
const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
|
|
19
65
|
const candidates = [];
|
|
@@ -462,7 +508,7 @@ const processMessage = async (message, { shouldProcessHistoryMsg, placeholderRes
|
|
|
462
508
|
break;
|
|
463
509
|
case proto.Message.ProtocolMessage.Type.LID_MIGRATION_MAPPING_SYNC:
|
|
464
510
|
const encodedPayload = protocolMsg.lidMigrationMappingSyncMessage?.encodedMappingPayload;
|
|
465
|
-
const { pnToLidMappings, chatDbMigrationTimestamp } =
|
|
511
|
+
const { pnToLidMappings, chatDbMigrationTimestamp } = decodeLidMigrationMappingSyncPayload(encodedPayload);
|
|
466
512
|
logger?.debug({ pnToLidMappings, chatDbMigrationTimestamp }, 'got lid mappings and chat db migration timestamp');
|
|
467
513
|
const pairs = [];
|
|
468
514
|
for (const { pn, latestLid, assignedLid } of pnToLidMappings) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vanzxy/baileys",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "Enhanced Baileys fork by Vanzxy — based on @itsliaaa/baileys + @whiskeysockets/baileys with fixes for audio group status and clean media without newsletter button.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./lib/index.js",
|