@vanzxy/baileys 1.5.6 → 1.5.8
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/Socket/chats.js
CHANGED
|
@@ -732,15 +732,37 @@ export const makeChatsSocket = (config) => {
|
|
|
732
732
|
ev.on('creds.update', onUpdate);
|
|
733
733
|
});
|
|
734
734
|
};
|
|
735
|
+
// Vanz@Fix (perf) --- appPatch() unconditionally round-tripped resyncAppState() to the WA
|
|
736
|
+
// server on EVERY single call, even for back-to-back patches (e.g. updateProfileName then
|
|
737
|
+
// immediately archiving/muting a chat) where the local version was already fresh from the
|
|
738
|
+
// resync a few hundred ms ago. That round trip is the main source of the multi-second delay
|
|
739
|
+
// people notice on things like "ganti nama". Cache the last-synced timestamp per collection
|
|
740
|
+
// name and skip the resync if it happened within RESYNC_TTL_MS — WA's own client does the
|
|
741
|
+
// same kind of short-lived debouncing. Set RESYNC_TTL_MS to 0 to restore the old always-resync
|
|
742
|
+
// behavior if this ever causes a stale-version conflict in practice.
|
|
743
|
+
const RESYNC_TTL_MS = 4000;
|
|
744
|
+
const lastResyncAt = new Map();
|
|
735
745
|
const appPatch = async (patchCreate) => {
|
|
736
746
|
const name = patchCreate.type;
|
|
747
|
+
const t0 = Date.now();
|
|
737
748
|
const myAppStateKeyId = await waitForAppStateKeyId();
|
|
749
|
+
const tKey = Date.now();
|
|
738
750
|
let initial;
|
|
739
751
|
let encodeResult;
|
|
740
752
|
await appStatePatchMutex.mutex(async () => {
|
|
741
753
|
await authState.keys.transaction(async () => {
|
|
742
754
|
logger.debug({ patch: patchCreate }, 'applying app patch');
|
|
743
|
-
|
|
755
|
+
const lastSync = lastResyncAt.get(name) ?? 0;
|
|
756
|
+
const freshEnough = RESYNC_TTL_MS > 0 && Date.now() - lastSync < RESYNC_TTL_MS;
|
|
757
|
+
if (!freshEnough) {
|
|
758
|
+
await resyncAppState([name], false);
|
|
759
|
+
lastResyncAt.set(name, Date.now());
|
|
760
|
+
}
|
|
761
|
+
const tResync = Date.now();
|
|
762
|
+
logger.debug(
|
|
763
|
+
{ patch: name, waitedForKeyMs: tKey - t0, resyncMs: freshEnough ? 0 : tResync - tKey, skippedResync: freshEnough },
|
|
764
|
+
'appPatch timing'
|
|
765
|
+
);
|
|
744
766
|
const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name]);
|
|
745
767
|
initial = currentSyncVersion ? ensureLTHashStateVersion(currentSyncVersion) : newLTHashState();
|
|
746
768
|
encodeResult = await encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
|
|
@@ -1068,6 +1090,11 @@ export const makeChatsSocket = (config) => {
|
|
|
1068
1090
|
if (syncState === SyncState.Syncing) {
|
|
1069
1091
|
// All collections will be synced, so clear any blocked ones
|
|
1070
1092
|
blockedCollections.clear();
|
|
1093
|
+
// Vanz@Fix (perf cache invalidation) --- a full sync is about to run for every
|
|
1094
|
+
// collection, so any per-collection "recently resynced" cache from appPatch()
|
|
1095
|
+
// is now stale by definition; drop it so the next appPatch() call resyncs fresh
|
|
1096
|
+
// instead of trusting a pre-full-sync timestamp.
|
|
1097
|
+
lastResyncAt.clear();
|
|
1071
1098
|
logger.info('Doing app state sync');
|
|
1072
1099
|
await resyncAppState(ALL_WA_PATCH_NAMES, true);
|
|
1073
1100
|
// Sync is complete, go online and flush everything
|
|
@@ -1129,6 +1156,9 @@ export const makeChatsSocket = (config) => {
|
|
|
1129
1156
|
ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
|
|
1130
1157
|
if (connection === 'close') {
|
|
1131
1158
|
blockedCollections.clear();
|
|
1159
|
+
// Vanz@Fix (perf cache invalidation) --- connection dropped, so any "recently
|
|
1160
|
+
// resynced" timestamps are no longer trustworthy once we reconnect.
|
|
1161
|
+
lastResyncAt.clear();
|
|
1132
1162
|
clearTimeout(historySyncPausedTimeout);
|
|
1133
1163
|
historySyncPausedTimeout = undefined;
|
|
1134
1164
|
}
|
|
@@ -336,6 +336,14 @@ class Toolkit {
|
|
|
336
336
|
|
|
337
337
|
const isWAUrl = (str) => /^https?:\/\/[^/]*\.whatsapp\.net\//i.test(str);
|
|
338
338
|
|
|
339
|
+
// Vanz@Fix (crash guard) --- keep the original raw url around so that if the
|
|
340
|
+
// resolveUrl=true upload-to-'@newsletter' round trip (Toolkit.toUrl -> prepareWAMessageMedia)
|
|
341
|
+
// throws/rejects (blocked account, network hiccup, WA server refusal, etc.), we can
|
|
342
|
+
// gracefully fall back to the raw url instead of letting the rejection bubble up
|
|
343
|
+
// unhandled through waitAllPromises() and take the whole process down. Only applies
|
|
344
|
+
// when the input was actually a url string; buffers/base64 have no such fallback.
|
|
345
|
+
const rawUrlFallback = typeof media === 'string' && isUrl(media) ? media : undefined;
|
|
346
|
+
|
|
339
347
|
if (Array.isArray(media)) {
|
|
340
348
|
return Promise.all(
|
|
341
349
|
media.map((item) =>
|
|
@@ -395,7 +403,16 @@ class Toolkit {
|
|
|
395
403
|
// same `Toolkit.toUrl(_client, media, mediaType)` call (dead branching left over from an
|
|
396
404
|
// earlier version that must have treated buffer vs non-buffer input differently). Collapsed
|
|
397
405
|
// to a single return; `originalIsBuffer` is now unused and removed below.
|
|
398
|
-
|
|
406
|
+
//
|
|
407
|
+
// Vanz@Fix (crash guard) --- toUrl() uploads to WA's media server under a spoofed
|
|
408
|
+
// '@newsletter' jid; if that upload fails for any reason, fall back to the raw url
|
|
409
|
+
// (when we have one) instead of letting the exception propagate and crash the caller.
|
|
410
|
+
try {
|
|
411
|
+
return await Toolkit.toUrl(_client, media, mediaType);
|
|
412
|
+
} catch (err) {
|
|
413
|
+
if (rawUrlFallback) return rawUrlFallback;
|
|
414
|
+
throw err;
|
|
415
|
+
}
|
|
399
416
|
}
|
|
400
417
|
|
|
401
418
|
/** Read an mp4 buffer's duration (seconds) straight from its moov atom, no ffprobe needed. */
|
|
@@ -1013,6 +1030,20 @@ class Button extends BaseBuilder {
|
|
|
1013
1030
|
}
|
|
1014
1031
|
|
|
1015
1032
|
|
|
1033
|
+
/** Native-flow `payment_key_info` shortcut. Payload is passed through unchanged. */
|
|
1034
|
+
addPaymentKeyInfo(payload = {}) {
|
|
1035
|
+
if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) throw new TypeError('addPaymentKeyInfo(payload) requires a plain object');
|
|
1036
|
+
this._buttons.push({ name: 'payment_key_info', buttonParamsJson: JSON.stringify(payload) });
|
|
1037
|
+
return this;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/** Native-flow `booking_confirmation` shortcut. Payload is passed through unchanged. */
|
|
1041
|
+
addBookingConfirmation(payload = {}) {
|
|
1042
|
+
if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) throw new TypeError('addBookingConfirmation(payload) requires a plain object');
|
|
1043
|
+
this._buttons.push({ name: 'booking_confirmation', buttonParamsJson: JSON.stringify(payload) });
|
|
1044
|
+
return this;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1016
1047
|
/** Native-flow `card_message` shortcut, matching this fork's prepareNativeFlowButtons(). */
|
|
1017
1048
|
addCardMessage(payload = {}) {
|
|
1018
1049
|
if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) throw new TypeError('addCardMessage(payload) requires a plain object');
|
|
@@ -1191,6 +1222,8 @@ class Button extends BaseBuilder {
|
|
|
1191
1222
|
send_location: { v: '2', name: 'send_location' },
|
|
1192
1223
|
call_permission_request: { v: '2', name: 'call_permission_request' },
|
|
1193
1224
|
wa_payment_transaction_details: { v: '2', name: 'wa_payment_transaction_details' },
|
|
1225
|
+
payment_key_info: { v: '1', name: 'payment_key_info' },
|
|
1226
|
+
booking_confirmation: { v: '1', name: 'booking_confirmation' },
|
|
1194
1227
|
automated_greeting_message_view_catalog: { v: '2', name: 'automated_greeting_message_view_catalog' },
|
|
1195
1228
|
};
|
|
1196
1229
|
|
|
@@ -160,6 +160,8 @@ export class AIRich extends BaseBuilder {
|
|
|
160
160
|
addText(text: string, options?: AddTextOptions): this;
|
|
161
161
|
addCode(language: string, code: string): this;
|
|
162
162
|
addTable(table: string[][], options?: AddTextOptions): this;
|
|
163
|
+
addPaymentKeyInfo(payload?: Record<string, any>): this;
|
|
164
|
+
addBookingConfirmation(payload?: Record<string, any>): this;
|
|
163
165
|
addLinks(links?: Record<string, any>[]): this;
|
|
164
166
|
addContentItems(items?: Record<string, any>[]): this;
|
|
165
167
|
addInlineVideo(): this;
|
|
@@ -128,15 +128,25 @@ export const toUnified = (submessages, uuid) => ({
|
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
130
|
case RichSubMessageType.TABLE:
|
|
131
|
-
const tableMetadata = submessage.tableMetadata;
|
|
131
|
+
const tableMetadata = submessage.tableMetadata || {};
|
|
132
|
+
// Accept both the internal row shape ({ items, isHeading }) and
|
|
133
|
+
// the raw string[][] shape used by some rich-response callers.
|
|
134
|
+
const rawRows = Array.isArray(tableMetadata.rows) ? tableMetadata.rows : [];
|
|
135
|
+
const normalizedRows = rawRows.map((row, index) => {
|
|
136
|
+
if (Array.isArray(row)) {
|
|
137
|
+
return { is_header: index === 0, cells: row.map(String) };
|
|
138
|
+
}
|
|
139
|
+
const cells = Array.isArray(row?.items) ? row.items.map(String) : [];
|
|
140
|
+
return { is_header: !!row?.isHeading, cells };
|
|
141
|
+
});
|
|
132
142
|
return {
|
|
133
143
|
view_model: {
|
|
134
144
|
primitive: {
|
|
135
|
-
title: tableMetadata.title,
|
|
136
|
-
rows:
|
|
137
|
-
is_header: row.
|
|
138
|
-
cells: row.
|
|
139
|
-
markdown_cells: row.
|
|
145
|
+
title: tableMetadata.title || '',
|
|
146
|
+
rows: normalizedRows.map((row) => ({
|
|
147
|
+
is_header: row.is_header,
|
|
148
|
+
cells: row.cells,
|
|
149
|
+
markdown_cells: row.cells.map((item) => ({ text: item }))
|
|
140
150
|
})),
|
|
141
151
|
__typename: 'GenATableUXPrimitive'
|
|
142
152
|
},
|
|
@@ -233,11 +243,16 @@ export const prepareRichResponseMessage = (content) => {
|
|
|
233
243
|
};
|
|
234
244
|
}
|
|
235
245
|
else if (submessage.table) {
|
|
246
|
+
const rows = Array.isArray(submessage.table)
|
|
247
|
+
? submessage.table.map((row, index) => Array.isArray(row)
|
|
248
|
+
? { isHeading: index === 0, items: row.map(String) }
|
|
249
|
+
: row)
|
|
250
|
+
: [];
|
|
236
251
|
return {
|
|
237
252
|
messageType: RichSubMessageType.TABLE,
|
|
238
253
|
tableMetadata: {
|
|
239
|
-
title: submessage.title,
|
|
240
|
-
rows
|
|
254
|
+
title: submessage.title || '',
|
|
255
|
+
rows
|
|
241
256
|
}
|
|
242
257
|
};
|
|
243
258
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vanzxy/baileys",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.8",
|
|
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",
|