@violetix/baileys 0.5.6 → 0.6.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/README.md +1530 -2009
- package/WAProto/index.d.ts +14030 -14586
- package/WAProto/index.js +58426 -88874
- package/lib/Defaults/index.d.ts +2 -7
- package/lib/Defaults/index.js +5 -20
- package/lib/Signal/Group/sender-key-message.js +19 -1
- package/lib/Signal/libsignal.js +82 -29
- package/lib/Signal/xeddsa-fast.js +114 -0
- package/lib/Socket/Client/types.js +6 -8
- package/lib/Socket/Client/websocket.js +3 -38
- package/lib/Socket/business.d.ts +0 -3
- package/lib/Socket/chats.d.ts +0 -3
- package/lib/Socket/chats.js +18 -45
- package/lib/Socket/communities.d.ts +0 -3
- package/lib/Socket/graphql.js +3 -7
- package/lib/Socket/groups.d.ts +0 -3
- package/lib/Socket/groups.js +3 -8
- package/lib/Socket/index.d.ts +15 -17
- package/lib/Socket/messages-recv.d.ts +0 -3
- package/lib/Socket/messages-recv.js +43 -127
- package/lib/Socket/messages-send.d.ts +0 -4
- package/lib/Socket/messages-send.js +63 -191
- package/lib/Socket/newsletter.d.ts +0 -3
- package/lib/Socket/newsletter.js +1 -2
- package/lib/Socket/newsletter.js.map +1 -1
- package/lib/Socket/socket.d.ts +0 -9
- package/lib/Socket/socket.js +53 -346
- package/lib/Store/make-in-memory-store.js +30 -41
- package/lib/Types/Auth.d.ts +2 -60
- package/lib/Types/Bussines.d.ts +2 -9
- package/lib/Types/Call.d.ts +2 -22
- package/lib/Types/Chat.d.ts +1 -2
- package/lib/Types/Contact.d.ts +2 -11
- package/lib/Types/Events.d.ts +2 -41
- package/lib/Types/GroupMetadata.d.ts +2 -36
- package/lib/Types/Message.d.ts +1 -11
- package/lib/Types/Product.d.ts +2 -5
- package/lib/Types/Signal.d.ts +2 -10
- package/lib/Types/Socket.d.ts +2 -33
- package/lib/Types/USync.d.ts +2 -9
- package/lib/Types/index.d.ts +1 -3
- package/lib/Utils/auth-utils.d.ts +2 -3
- package/lib/Utils/auth-utils.js +53 -37
- package/lib/Utils/business.js +11 -25
- package/lib/Utils/chat-utils.js +4 -6
- package/lib/Utils/decode-wa-message.js +2 -2
- package/lib/Utils/event-buffer.js +12 -21
- package/lib/Utils/generics.d.ts +5 -5
- package/lib/Utils/generics.js +7 -25
- package/lib/Utils/history.d.ts +1 -2
- package/lib/Utils/history.js +83 -137
- package/lib/Utils/index.d.ts +0 -4
- package/lib/Utils/index.js +0 -4
- package/lib/Utils/listener-guard.js +0 -2
- package/lib/Utils/message-retry-manager.js +0 -20
- package/lib/Utils/messages-media.d.ts +8 -39
- package/lib/Utils/messages-media.js +89 -218
- package/lib/Utils/messages.d.ts +0 -1
- package/lib/Utils/messages.js +36 -122
- package/lib/Utils/process-message.d.ts +0 -18
- package/lib/Utils/process-message.js +47 -99
- package/lib/Utils/rich-message-utils.js +4 -3
- package/lib/Utils/use-multi-file-auth-state.d.ts +3 -5
- package/lib/Utils/use-multi-file-auth-state.js +6 -27
- package/lib/Utils/use-single-file-auth-state.d.ts +1 -1
- package/lib/Utils/use-single-file-auth-state.js +3 -12
- package/lib/WABinary/types.d.ts +2 -6
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +3 -6
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +2 -3
- package/lib/WAUSync/USyncQuery.d.ts +1 -1
- package/lib/WAUSync/USyncQuery.js +4 -7
- package/package.json +107 -123
- package/lib/Utils/a2ui.d.ts +0 -50
- package/lib/Utils/a2ui.js +0 -168
- package/lib/Utils/anchor-guard.d.ts +0 -71
- package/lib/Utils/anchor-guard.js +0 -404
- package/lib/Utils/connection-manager.d.ts +0 -44
- package/lib/Utils/connection-manager.js +0 -258
- package/lib/Utils/ignore-key.d.ts +0 -51
- package/lib/Utils/ignore-key.js +0 -176
package/lib/Utils/auth-utils.js
CHANGED
|
@@ -61,7 +61,6 @@ export function makeCacheableSignalKeyStore(store, logger, _cache) {
|
|
|
61
61
|
},
|
|
62
62
|
async set(data) {
|
|
63
63
|
return cacheMutex.runExclusive(async () => {
|
|
64
|
-
await store.set(data);
|
|
65
64
|
let keys = 0;
|
|
66
65
|
for (const type in data) {
|
|
67
66
|
for (const id in data[type]) {
|
|
@@ -70,13 +69,12 @@ export function makeCacheableSignalKeyStore(store, logger, _cache) {
|
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
71
|
logger?.trace({ keys }, 'updated cache');
|
|
72
|
+
await store.set(data);
|
|
73
73
|
});
|
|
74
74
|
},
|
|
75
75
|
async clear() {
|
|
76
|
-
await
|
|
77
|
-
|
|
78
|
-
await cache.flushAll();
|
|
79
|
-
});
|
|
76
|
+
await cache.flushAll();
|
|
77
|
+
await store.clear?.();
|
|
80
78
|
}
|
|
81
79
|
};
|
|
82
80
|
}
|
|
@@ -93,12 +91,35 @@ export const addTransactionCapability = (state, logger, { maxCommitRetries, dela
|
|
|
93
91
|
const txMutexRefCounts = new Map();
|
|
94
92
|
// Pre-key manager for specialized operations
|
|
95
93
|
const preKeyManager = new PreKeyManager(state, logger);
|
|
96
|
-
|
|
94
|
+
// Debounced writer: collects writes within a window and flushes as one SQLite tx
|
|
95
|
+
const debounceWindow = 5000;
|
|
96
|
+
let debounceTimer = null;
|
|
97
|
+
let debouncedData = {};
|
|
98
|
+
// One writer at a time. A debounced flush and a transaction commit both call state.set, and
|
|
99
|
+
// interleaving them lets an older debounced value land on top of a newer committed one.
|
|
97
100
|
const writeMutex = new Mutex();
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
const flushDebounced = async () => {
|
|
102
|
+
if (debounceTimer) {
|
|
103
|
+
clearTimeout(debounceTimer);
|
|
104
|
+
debounceTimer = null;
|
|
105
|
+
}
|
|
106
|
+
const data = debouncedData;
|
|
107
|
+
debouncedData = {};
|
|
108
|
+
if (Object.keys(data).length === 0) return;
|
|
109
|
+
// All types in one call: that is the single SQLite transaction this debounce exists for.
|
|
110
|
+
await writeMutex.runExclusive(() => state.set(data));
|
|
111
|
+
};
|
|
112
|
+
const scheduleFlush = () => {
|
|
113
|
+
// Max age, not a sliding window: re-arming the timer on every write meant a socket that
|
|
114
|
+
// never went quiet for a full window never flushed at all, leaving ratchet state in memory
|
|
115
|
+
// only until the process happened to die.
|
|
116
|
+
if (debounceTimer) return;
|
|
117
|
+
debounceTimer = setTimeout(() => {
|
|
118
|
+
// The timer has nowhere to report to, and an unhandled rejection here takes down the
|
|
119
|
+
// whole process - every other session in it included.
|
|
120
|
+
flushDebounced().catch(err => logger.error({ err }, 'failed to flush signal keys'));
|
|
121
|
+
}, debounceWindow);
|
|
122
|
+
};
|
|
102
123
|
/**
|
|
103
124
|
* Get or create a transaction mutex
|
|
104
125
|
*/
|
|
@@ -135,7 +156,7 @@ export const addTransactionCapability = (state, logger, { maxCommitRetries, dela
|
|
|
135
156
|
* Check if currently in a transaction
|
|
136
157
|
*/
|
|
137
158
|
function isInTransaction() {
|
|
138
|
-
return !!
|
|
159
|
+
return !!txStorage.getStore();
|
|
139
160
|
}
|
|
140
161
|
/**
|
|
141
162
|
* Commit transaction with retries
|
|
@@ -146,15 +167,17 @@ export const addTransactionCapability = (state, logger, { maxCommitRetries, dela
|
|
|
146
167
|
return;
|
|
147
168
|
}
|
|
148
169
|
logger.trace('committing transaction');
|
|
149
|
-
|
|
150
|
-
|
|
170
|
+
// Whatever is still debounced was written BEFORE these mutations, so it has to land first
|
|
171
|
+
// or it overwrites them.
|
|
172
|
+
await flushDebounced();
|
|
173
|
+
for (let attempt = 0; attempt < maxCommitRetries; attempt++) {
|
|
151
174
|
try {
|
|
152
175
|
await writeMutex.runExclusive(() => state.set(mutations));
|
|
153
176
|
logger.trace({ mutationCount: Object.keys(mutations).length }, 'committed transaction');
|
|
154
177
|
return;
|
|
155
178
|
}
|
|
156
179
|
catch (error) {
|
|
157
|
-
const retriesLeft =
|
|
180
|
+
const retriesLeft = maxCommitRetries - attempt - 1;
|
|
158
181
|
logger.warn(`failed to commit mutations, retries left=${retriesLeft}`);
|
|
159
182
|
if (retriesLeft === 0) {
|
|
160
183
|
throw error;
|
|
@@ -165,7 +188,7 @@ export const addTransactionCapability = (state, logger, { maxCommitRetries, dela
|
|
|
165
188
|
}
|
|
166
189
|
return {
|
|
167
190
|
get: async (type, ids) => {
|
|
168
|
-
const ctx =
|
|
191
|
+
const ctx = txStorage.getStore();
|
|
169
192
|
if (!ctx) {
|
|
170
193
|
// No transaction - direct read without exclusive lock for concurrency
|
|
171
194
|
return state.get(type, ids);
|
|
@@ -176,7 +199,7 @@ export const addTransactionCapability = (state, logger, { maxCommitRetries, dela
|
|
|
176
199
|
if (missing.length > 0) {
|
|
177
200
|
ctx.dbQueries++;
|
|
178
201
|
logger.trace({ type, count: missing.length }, 'fetching missing keys in transaction');
|
|
179
|
-
const fetched = await state.get(type, missing);
|
|
202
|
+
const fetched = await getTxMutex(type).runExclusive(() => state.get(type, missing));
|
|
180
203
|
// Update cache
|
|
181
204
|
ctx.cache[type] = ctx.cache[type] || {};
|
|
182
205
|
Object.assign(ctx.cache[type], fetched);
|
|
@@ -192,14 +215,18 @@ export const addTransactionCapability = (state, logger, { maxCommitRetries, dela
|
|
|
192
215
|
return result;
|
|
193
216
|
},
|
|
194
217
|
set: async (data) => {
|
|
195
|
-
const ctx =
|
|
218
|
+
const ctx = txStorage.getStore();
|
|
196
219
|
if (!ctx) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
220
|
+
// No transaction - debounce writes to batch into fewer SQLite transactions
|
|
221
|
+
for (const type_ in data) {
|
|
222
|
+
const type = type_;
|
|
223
|
+
if (type === 'pre-key') {
|
|
224
|
+
await preKeyManager.validateDeletions(data, type);
|
|
200
225
|
}
|
|
201
|
-
|
|
202
|
-
}
|
|
226
|
+
debouncedData[type] = { ...debouncedData[type], ...data[type] };
|
|
227
|
+
}
|
|
228
|
+
scheduleFlush();
|
|
229
|
+
return;
|
|
203
230
|
}
|
|
204
231
|
// In transaction - update cache and mutations
|
|
205
232
|
logger.trace({ types: Object.keys(data) }, 'caching in transaction');
|
|
@@ -221,7 +248,7 @@ export const addTransactionCapability = (state, logger, { maxCommitRetries, dela
|
|
|
221
248
|
},
|
|
222
249
|
isInTransaction,
|
|
223
250
|
transaction: async (work, key) => {
|
|
224
|
-
const existing =
|
|
251
|
+
const existing = txStorage.getStore();
|
|
225
252
|
// Nested transaction - reuse existing context
|
|
226
253
|
if (existing) {
|
|
227
254
|
logger.trace('reusing existing transaction context');
|
|
@@ -233,19 +260,13 @@ export const addTransactionCapability = (state, logger, { maxCommitRetries, dela
|
|
|
233
260
|
try {
|
|
234
261
|
return await mutex.runExclusive(async () => {
|
|
235
262
|
const ctx = {
|
|
236
|
-
active: true,
|
|
237
263
|
cache: {},
|
|
238
264
|
mutations: {},
|
|
239
265
|
dbQueries: 0
|
|
240
266
|
};
|
|
241
|
-
const contexts = new Map(txStorage.getStore());
|
|
242
|
-
contexts.set(storeToken, ctx);
|
|
243
267
|
logger.trace('entering transaction');
|
|
244
268
|
try {
|
|
245
|
-
const result = await txStorage.run(
|
|
246
|
-
// Detached async work can outlive this callback. It must not write into
|
|
247
|
-
// a context whose mutations have already been handed to the commit.
|
|
248
|
-
ctx.active = false;
|
|
269
|
+
const result = await txStorage.run(ctx, work);
|
|
249
270
|
// Commit mutations
|
|
250
271
|
await commitWithRetry(ctx.mutations);
|
|
251
272
|
logger.trace({ dbQueries: ctx.dbQueries }, 'transaction completed');
|
|
@@ -255,18 +276,13 @@ export const addTransactionCapability = (state, logger, { maxCommitRetries, dela
|
|
|
255
276
|
logger.error({ error }, 'transaction failed, rolling back');
|
|
256
277
|
throw error;
|
|
257
278
|
}
|
|
258
|
-
finally {
|
|
259
|
-
ctx.active = false;
|
|
260
|
-
}
|
|
261
279
|
});
|
|
262
280
|
}
|
|
263
281
|
finally {
|
|
264
282
|
releaseTxMutexRef(key);
|
|
265
283
|
}
|
|
266
284
|
},
|
|
267
|
-
flush:
|
|
268
|
-
await state.flush?.();
|
|
269
|
-
})
|
|
285
|
+
flush: flushDebounced
|
|
270
286
|
};
|
|
271
287
|
};
|
|
272
288
|
/**
|
|
@@ -303,4 +319,4 @@ export const initAuthCreds = () => {
|
|
|
303
319
|
additionalData: undefined
|
|
304
320
|
};
|
|
305
321
|
};
|
|
306
|
-
//# sourceMappingURL=auth-utils.js.map
|
|
322
|
+
//# sourceMappingURL=auth-utils.js.map
|
package/lib/Utils/business.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
|
-
import { once } from 'events';
|
|
4
3
|
import { createWriteStream, promises as fs } from 'fs';
|
|
5
4
|
import { tmpdir } from 'os';
|
|
6
5
|
import { join } from 'path';
|
|
@@ -200,31 +199,18 @@ export const uploadingNecessaryImages = async (images, waUploadToServer, timeout
|
|
|
200
199
|
const hasher = createHash('sha256');
|
|
201
200
|
const filePath = join(tmpdir(), 'img' + generateMessageIDV2());
|
|
202
201
|
const encFileWriteStream = createWriteStream(filePath);
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
// Respect backpressure instead of queueing the whole image in memory.
|
|
207
|
-
if (!encFileWriteStream.write(block)) {
|
|
208
|
-
await once(encFileWriteStream, 'drain');
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
// The upload reads the path, so the writes have to be on disk first. Without this the
|
|
212
|
-
// upload could read a partial file while the hash covers the whole image, and the
|
|
213
|
-
// server rejects the mismatch.
|
|
214
|
-
await new Promise((resolve, reject) => encFileWriteStream.end(err => (err ? reject(err) : resolve())));
|
|
215
|
-
const sha = hasher.digest('base64');
|
|
216
|
-
const { directPath } = await waUploadToServer(filePath, {
|
|
217
|
-
mediaType: 'product-catalog-image',
|
|
218
|
-
fileEncSha256B64: sha,
|
|
219
|
-
timeoutMs
|
|
220
|
-
});
|
|
221
|
-
return { url: getUrlFromDirectPath(directPath) };
|
|
222
|
-
}
|
|
223
|
-
finally {
|
|
224
|
-
// Also runs when the upload throws, which used to leak the temp file.
|
|
225
|
-
encFileWriteStream.destroy();
|
|
226
|
-
await fs.unlink(filePath).catch(() => { });
|
|
202
|
+
for await (const block of stream) {
|
|
203
|
+
hasher.update(block);
|
|
204
|
+
encFileWriteStream.write(block);
|
|
227
205
|
}
|
|
206
|
+
const sha = hasher.digest('base64');
|
|
207
|
+
const { directPath } = await waUploadToServer(filePath, {
|
|
208
|
+
mediaType: 'product-catalog-image',
|
|
209
|
+
fileEncSha256B64: sha,
|
|
210
|
+
timeoutMs
|
|
211
|
+
});
|
|
212
|
+
await fs.unlink(filePath).catch(err => console.log('Error deleting temp file ', err));
|
|
213
|
+
return { url: getUrlFromDirectPath(directPath) };
|
|
228
214
|
}));
|
|
229
215
|
return results;
|
|
230
216
|
};
|
package/lib/Utils/chat-utils.js
CHANGED
|
@@ -344,6 +344,7 @@ export const decodePatches = async (name, syncds, initial, getAppStateSyncKey, o
|
|
|
344
344
|
syncd.mutations?.push(...ref.mutations);
|
|
345
345
|
}
|
|
346
346
|
const patchVersion = toNumber(version.version);
|
|
347
|
+
newState.version = patchVersion;
|
|
347
348
|
const shouldMutate = typeof minimumVersionNumber === 'undefined' || patchVersion > minimumVersionNumber;
|
|
348
349
|
let decodeResult;
|
|
349
350
|
try {
|
|
@@ -357,12 +358,9 @@ export const decodePatches = async (name, syncds, initial, getAppStateSyncKey, o
|
|
|
357
358
|
catch (err) {
|
|
358
359
|
if (isMissingKeyError(err))
|
|
359
360
|
throw err;
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
logger?.warn({ name, version: patchVersion, error: err.message }, 'failed to decode patch, stopping');
|
|
363
|
-
break;
|
|
361
|
+
logger?.warn({ name, version: patchVersion, error: err.message }, 'failed to decode patch, skipping');
|
|
362
|
+
continue;
|
|
364
363
|
}
|
|
365
|
-
newState.version = patchVersion;
|
|
366
364
|
newState.hash = decodeResult.hash;
|
|
367
365
|
newState.indexValueMap = decodeResult.indexValueMap;
|
|
368
366
|
if (validateMacs) {
|
|
@@ -732,7 +730,7 @@ export const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) =
|
|
|
732
730
|
}
|
|
733
731
|
else if (action?.pushNameSetting) {
|
|
734
732
|
const name = action?.pushNameSetting?.name;
|
|
735
|
-
if (name && me?.
|
|
733
|
+
if (name && me?.name !== name) {
|
|
736
734
|
ev.emit('creds.update', { me: { ...me, name } });
|
|
737
735
|
}
|
|
738
736
|
}
|
|
@@ -192,7 +192,7 @@ export function decodeMessageNode(stanza, meId, meLid) {
|
|
|
192
192
|
if (!participant) {
|
|
193
193
|
throw new Boom('No participant in group message');
|
|
194
194
|
}
|
|
195
|
-
const isParticipantMe = isMe(participant)
|
|
195
|
+
const isParticipantMe = isMe(participant);
|
|
196
196
|
if (isJidStatusBroadcast(from)) {
|
|
197
197
|
msgType = isParticipantMe ? 'direct_peer_status' : 'other_status';
|
|
198
198
|
}
|
|
@@ -226,7 +226,7 @@ export function decodeMessageNode(stanza, meId, meLid) {
|
|
|
226
226
|
remoteJid: chatId,
|
|
227
227
|
remoteJidAlt: !isJidGroup(chatId) ? addressingContext.senderAlt : undefined,
|
|
228
228
|
remoteJidUsername: !isJidGroup(chatId)
|
|
229
|
-
? stanza.attrs.peer_recipient_username || stanza.attrs.recipient_username
|
|
229
|
+
? stanza.attrs.peer_recipient_username || stanza.attrs.recipient_username
|
|
230
230
|
: undefined,
|
|
231
231
|
fromMe,
|
|
232
232
|
id: msgId,
|
|
@@ -26,7 +26,7 @@ const BUFFERABLE_EVENT_SET = new Set(BUFFERABLE_EVENT);
|
|
|
26
26
|
export const makeEventBuffer = (logger) => {
|
|
27
27
|
const ev = new EventEmitter();
|
|
28
28
|
const historyCache = new Set();
|
|
29
|
-
|
|
29
|
+
const trackedListeners = [];
|
|
30
30
|
let data = makeBufferData();
|
|
31
31
|
let isBuffering = false;
|
|
32
32
|
let bufferTimeout = null;
|
|
@@ -108,7 +108,9 @@ export const makeEventBuffer = (logger) => {
|
|
|
108
108
|
}
|
|
109
109
|
return {
|
|
110
110
|
process(handler) {
|
|
111
|
-
const listener =
|
|
111
|
+
const listener = async (map) => {
|
|
112
|
+
await handler(map);
|
|
113
|
+
};
|
|
112
114
|
ev.on('event', listener);
|
|
113
115
|
return () => {
|
|
114
116
|
ev.off('event', listener);
|
|
@@ -179,20 +181,8 @@ export const makeEventBuffer = (logger) => {
|
|
|
179
181
|
on: (...args) => { trackedOn(...args); return ev; },
|
|
180
182
|
// unwrap, or removal would look for the caller's function while the registration holds the
|
|
181
183
|
// guarded wrapper - every off() would silently leave the listener attached.
|
|
182
|
-
off: (event, handler) =>
|
|
183
|
-
|
|
184
|
-
const result = ev.off(event, guarded);
|
|
185
|
-
const index = trackedListeners.findLastIndex(([name, listener]) => name === event && listener === guarded);
|
|
186
|
-
if (index !== -1) {
|
|
187
|
-
trackedListeners.splice(index, 1);
|
|
188
|
-
}
|
|
189
|
-
return result;
|
|
190
|
-
},
|
|
191
|
-
removeAllListeners: (...args) => {
|
|
192
|
-
const result = ev.removeAllListeners(...args);
|
|
193
|
-
trackedListeners = args.length ? trackedListeners.filter(([event]) => event !== args[0]) : [];
|
|
194
|
-
return result;
|
|
195
|
-
},
|
|
184
|
+
off: (event, handler) => ev.off(event, listenerGuard.unwrap(handler)),
|
|
185
|
+
removeAllListeners: (...args) => ev.removeAllListeners(...args),
|
|
196
186
|
removeTrackedListeners() {
|
|
197
187
|
for (const [event, handler] of trackedListeners) {
|
|
198
188
|
ev.off(event, handler);
|
|
@@ -400,8 +390,7 @@ eventData, logger) {
|
|
|
400
390
|
data.contactUpserts[contact.id] = upsert;
|
|
401
391
|
}
|
|
402
392
|
if (data.contactUpdates[contact.id]) {
|
|
403
|
-
|
|
404
|
-
Object.assign(upsert, trimUndefined(data.contactUpdates[contact.id]), trimUndefined(contact));
|
|
393
|
+
upsert = Object.assign(data.contactUpdates[contact.id], trimUndefined(contact));
|
|
405
394
|
delete data.contactUpdates[contact.id];
|
|
406
395
|
}
|
|
407
396
|
}
|
|
@@ -526,8 +515,10 @@ eventData, logger) {
|
|
|
526
515
|
const groupUpdates = eventData;
|
|
527
516
|
for (const update of groupUpdates) {
|
|
528
517
|
const id = update.id;
|
|
529
|
-
|
|
530
|
-
|
|
518
|
+
const groupUpdate = data.groupUpdates[id] || {};
|
|
519
|
+
if (!data.groupUpdates[id]) {
|
|
520
|
+
data.groupUpdates[id] = Object.assign(groupUpdate, update);
|
|
521
|
+
}
|
|
531
522
|
}
|
|
532
523
|
break;
|
|
533
524
|
default:
|
|
@@ -647,4 +638,4 @@ function concatChats(a, b) {
|
|
|
647
638
|
return Object.assign(a, b);
|
|
648
639
|
}
|
|
649
640
|
const stringifyMessageKey = (key) => `${key.remoteJid},${key.id},${key.fromMe ? '1' : '0'}`;
|
|
650
|
-
//# sourceMappingURL=event-buffer.js.map
|
|
641
|
+
//# sourceMappingURL=event-buffer.js.map
|
package/lib/Utils/generics.d.ts
CHANGED
|
@@ -32,20 +32,20 @@ export function generateMessageIDV2(userId: any): string;
|
|
|
32
32
|
export function generateMessageID(): string;
|
|
33
33
|
export function bindWaitForConnectionUpdate(ev: any): (check: any, timeoutMs: any) => Promise<void>;
|
|
34
34
|
export function fetchLatestBaileysVersion(options?: {}): Promise<{
|
|
35
|
-
version: [
|
|
35
|
+
version: number[];
|
|
36
36
|
isLatest: boolean;
|
|
37
37
|
error?: undefined;
|
|
38
38
|
} | {
|
|
39
|
-
version: [
|
|
39
|
+
version: number[];
|
|
40
40
|
isLatest: boolean;
|
|
41
41
|
error: unknown;
|
|
42
42
|
}>;
|
|
43
43
|
export function fetchLatestWaWebVersion(options?: {}): Promise<{
|
|
44
|
-
version: [
|
|
44
|
+
version: number[];
|
|
45
45
|
isLatest: boolean;
|
|
46
46
|
error?: undefined;
|
|
47
47
|
} | {
|
|
48
|
-
version: [
|
|
48
|
+
version: number[];
|
|
49
49
|
isLatest: boolean;
|
|
50
50
|
error: unknown;
|
|
51
51
|
}>;
|
|
@@ -61,4 +61,4 @@ export function getCallStatusFromNode({ tag, attrs }: {
|
|
|
61
61
|
}): string;
|
|
62
62
|
export function getCodeFromWSError(error: any): number;
|
|
63
63
|
export function isWABusinessPlatform(platform: any): boolean;
|
|
64
|
-
//# sourceMappingURL=generics.d.ts.map
|
|
64
|
+
//# sourceMappingURL=generics.d.ts.map
|
package/lib/Utils/generics.js
CHANGED
|
@@ -204,13 +204,10 @@ export const fetchLatestWaWebVersion = async (options = {}) => {
|
|
|
204
204
|
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
|
|
205
205
|
};
|
|
206
206
|
const headers = { ...defaultHeaders, ...options.headers };
|
|
207
|
-
// bounded: a hung sw.js fetch must not stall the connect path that awaits this
|
|
208
|
-
const signal = options.signal ?? AbortSignal.timeout(options.timeoutMs ?? 10000);
|
|
209
207
|
const response = await fetch('https://web.whatsapp.com/sw.js', {
|
|
210
208
|
...options,
|
|
211
209
|
method: 'GET',
|
|
212
|
-
headers
|
|
213
|
-
signal
|
|
210
|
+
headers
|
|
214
211
|
});
|
|
215
212
|
if (!response.ok) {
|
|
216
213
|
throw new Boom(`Failed to fetch sw.js: ${response.statusText}`, { statusCode: response.status });
|
|
@@ -263,32 +260,17 @@ export const getStatusFromReceiptType = (type) => {
|
|
|
263
260
|
}
|
|
264
261
|
return status;
|
|
265
262
|
};
|
|
263
|
+
const CODE_MAP = {
|
|
264
|
+
conflict: DisconnectReason.connectionReplaced
|
|
265
|
+
};
|
|
266
266
|
/**
|
|
267
|
-
* Stream errors generally provide a reason, map that to a baileys DisconnectReason
|
|
268
|
-
*
|
|
269
|
-
* ack / xml-not-well-formed / unknown reasons are transient and must stay reconnectable.
|
|
270
|
-
* The old fallback was badSession (500), which made bots wipe healthy sessions.
|
|
267
|
+
* Stream errors generally provide a reason, map that to a baileys DisconnectReason
|
|
268
|
+
* @param reason the string reason given, eg. "conflict"
|
|
271
269
|
*/
|
|
272
270
|
export const getErrorCodeFromStreamError = (node) => {
|
|
273
271
|
const [reasonNode] = getAllBinaryNodeChildren(node);
|
|
274
272
|
let reason = reasonNode?.tag || 'unknown';
|
|
275
|
-
|
|
276
|
-
if (reason === 'conflict') {
|
|
277
|
-
// type="replaced": another client took over; any other type (device_removed): unlinked
|
|
278
|
-
statusCode = reasonNode.attrs?.type === 'replaced' || !reasonNode.attrs?.type
|
|
279
|
-
? DisconnectReason.connectionReplaced
|
|
280
|
-
: DisconnectReason.loggedOut;
|
|
281
|
-
}
|
|
282
|
-
else if (node.attrs.code) {
|
|
283
|
-
statusCode = +node.attrs.code;
|
|
284
|
-
// 516 = server-forced logout
|
|
285
|
-
if (statusCode === 516) {
|
|
286
|
-
statusCode = DisconnectReason.loggedOut;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
else {
|
|
290
|
-
statusCode = DisconnectReason.connectionClosed;
|
|
291
|
-
}
|
|
273
|
+
const statusCode = +(node.attrs.code || CODE_MAP[reason] || DisconnectReason.badSession);
|
|
292
274
|
if (statusCode === DisconnectReason.restartRequired) {
|
|
293
275
|
reason = 'restart required';
|
|
294
276
|
}
|
package/lib/Utils/history.d.ts
CHANGED
|
@@ -73,5 +73,4 @@ export function downloadAndProcessHistorySyncNotification(msg: any, options: any
|
|
|
73
73
|
}>;
|
|
74
74
|
export function getHistoryMsg(message: any): any;
|
|
75
75
|
import { proto } from '../../WAProto/index.js';
|
|
76
|
-
//# sourceMappingURL=history.d.ts.map
|
|
77
|
-
export function decodeHistorySyncStreaming(buffer: Uint8Array, onConversation: (conversation: proto.IConversation) => void): proto.HistorySync;
|
|
76
|
+
//# sourceMappingURL=history.d.ts.map
|