Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MR414N-ID
GitHub Repository: MR414N-ID/botku2
Path: blob/master/node_modules/@adiwajshing/baileys/lib/Utils/chat-utils.js
1129 views
1
"use strict";
2
Object.defineProperty(exports, "__esModule", { value: true });
3
exports.processSyncAction = exports.chatModificationToAppPatch = exports.decodePatches = exports.decodeSyncdSnapshot = exports.downloadExternalPatch = exports.downloadExternalBlob = exports.extractSyncdPatches = exports.decodeSyncdPatch = exports.decodeSyncdMutations = exports.encodeSyncdPatch = exports.newLTHashState = void 0;
4
const boom_1 = require("@hapi/boom");
5
const WAProto_1 = require("../../WAProto");
6
const WABinary_1 = require("../WABinary");
7
const crypto_1 = require("./crypto");
8
const generics_1 = require("./generics");
9
const lt_hash_1 = require("./lt-hash");
10
const messages_media_1 = require("./messages-media");
11
const mutationKeys = (keydata) => {
12
const expanded = (0, crypto_1.hkdf)(keydata, 160, { info: 'WhatsApp Mutation Keys' });
13
return {
14
indexKey: expanded.slice(0, 32),
15
valueEncryptionKey: expanded.slice(32, 64),
16
valueMacKey: expanded.slice(64, 96),
17
snapshotMacKey: expanded.slice(96, 128),
18
patchMacKey: expanded.slice(128, 160)
19
};
20
};
21
const generateMac = (operation, data, keyId, key) => {
22
const getKeyData = () => {
23
let r;
24
switch (operation) {
25
case WAProto_1.proto.SyncdMutation.SyncdOperation.SET:
26
r = 0x01;
27
break;
28
case WAProto_1.proto.SyncdMutation.SyncdOperation.REMOVE:
29
r = 0x02;
30
break;
31
}
32
const buff = Buffer.from([r]);
33
return Buffer.concat([buff, Buffer.from(keyId, 'base64')]);
34
};
35
const keyData = getKeyData();
36
const last = Buffer.alloc(8); // 8 bytes
37
last.set([keyData.length], last.length - 1);
38
const total = Buffer.concat([keyData, data, last]);
39
const hmac = (0, crypto_1.hmacSign)(total, key, 'sha512');
40
return hmac.slice(0, 32);
41
};
42
const to64BitNetworkOrder = (e) => {
43
const t = new ArrayBuffer(8);
44
new DataView(t).setUint32(4, e, !1);
45
return Buffer.from(t);
46
};
47
const makeLtHashGenerator = ({ indexValueMap, hash }) => {
48
indexValueMap = { ...indexValueMap };
49
const addBuffs = [];
50
const subBuffs = [];
51
return {
52
mix: ({ indexMac, valueMac, operation }) => {
53
const indexMacBase64 = Buffer.from(indexMac).toString('base64');
54
const prevOp = indexValueMap[indexMacBase64];
55
if (operation === WAProto_1.proto.SyncdMutation.SyncdOperation.REMOVE) {
56
if (!prevOp) {
57
throw new boom_1.Boom('tried remove, but no previous op', { data: { indexMac, valueMac } });
58
}
59
// remove from index value mac, since this mutation is erased
60
delete indexValueMap[indexMacBase64];
61
}
62
else {
63
addBuffs.push(new Uint8Array(valueMac).buffer);
64
// add this index into the history map
65
indexValueMap[indexMacBase64] = { valueMac };
66
}
67
if (prevOp) {
68
subBuffs.push(new Uint8Array(prevOp.valueMac).buffer);
69
}
70
},
71
finish: () => {
72
const result = lt_hash_1.LT_HASH_ANTI_TAMPERING.subtractThenAdd(new Uint8Array(hash).buffer, addBuffs, subBuffs);
73
const buffer = Buffer.from(result);
74
return {
75
hash: buffer,
76
indexValueMap
77
};
78
}
79
};
80
};
81
const generateSnapshotMac = (lthash, version, name, key) => {
82
const total = Buffer.concat([
83
lthash,
84
to64BitNetworkOrder(version),
85
Buffer.from(name, 'utf-8')
86
]);
87
return (0, crypto_1.hmacSign)(total, key, 'sha256');
88
};
89
const generatePatchMac = (snapshotMac, valueMacs, version, type, key) => {
90
const total = Buffer.concat([
91
snapshotMac,
92
...valueMacs,
93
to64BitNetworkOrder(version),
94
Buffer.from(type, 'utf-8')
95
]);
96
return (0, crypto_1.hmacSign)(total, key);
97
};
98
const newLTHashState = () => ({ version: 0, hash: Buffer.alloc(128), indexValueMap: {} });
99
exports.newLTHashState = newLTHashState;
100
const encodeSyncdPatch = async ({ type, index, syncAction, apiVersion, operation }, myAppStateKeyId, state, getAppStateSyncKey) => {
101
const key = !!myAppStateKeyId ? await getAppStateSyncKey(myAppStateKeyId) : undefined;
102
if (!key) {
103
throw new boom_1.Boom(`myAppStateKey ("${myAppStateKeyId}") not present`, { statusCode: 404 });
104
}
105
const encKeyId = Buffer.from(myAppStateKeyId, 'base64');
106
state = { ...state, indexValueMap: { ...state.indexValueMap } };
107
const indexBuffer = Buffer.from(JSON.stringify(index));
108
const dataProto = WAProto_1.proto.SyncActionData.fromObject({
109
index: indexBuffer,
110
value: syncAction,
111
padding: new Uint8Array(0),
112
version: apiVersion
113
});
114
const encoded = WAProto_1.proto.SyncActionData.encode(dataProto).finish();
115
const keyValue = mutationKeys(key.keyData);
116
const encValue = (0, crypto_1.aesEncrypt)(encoded, keyValue.valueEncryptionKey);
117
const valueMac = generateMac(operation, encValue, encKeyId, keyValue.valueMacKey);
118
const indexMac = (0, crypto_1.hmacSign)(indexBuffer, keyValue.indexKey);
119
// update LT hash
120
const generator = makeLtHashGenerator(state);
121
generator.mix({ indexMac, valueMac, operation });
122
Object.assign(state, generator.finish());
123
state.version += 1;
124
const snapshotMac = generateSnapshotMac(state.hash, state.version, type, keyValue.snapshotMacKey);
125
const patch = {
126
patchMac: generatePatchMac(snapshotMac, [valueMac], state.version, type, keyValue.patchMacKey),
127
snapshotMac: snapshotMac,
128
keyId: { id: encKeyId },
129
mutations: [
130
{
131
operation: operation,
132
record: {
133
index: {
134
blob: indexMac
135
},
136
value: {
137
blob: Buffer.concat([encValue, valueMac])
138
},
139
keyId: { id: encKeyId }
140
}
141
}
142
]
143
};
144
const base64Index = indexMac.toString('base64');
145
state.indexValueMap[base64Index] = { valueMac };
146
return { patch, state };
147
};
148
exports.encodeSyncdPatch = encodeSyncdPatch;
149
const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncKey, onMutation, validateMacs) => {
150
const keyCache = {};
151
const getKey = async (keyId) => {
152
const base64Key = Buffer.from(keyId).toString('base64');
153
let key = keyCache[base64Key];
154
if (!key) {
155
const keyEnc = await getAppStateSyncKey(base64Key);
156
if (!keyEnc) {
157
throw new boom_1.Boom(`failed to find key "${base64Key}" to decode mutation`, { statusCode: 404, data: { msgMutations } });
158
}
159
const result = mutationKeys(keyEnc.keyData);
160
keyCache[base64Key] = result;
161
key = result;
162
}
163
return key;
164
};
165
const ltGenerator = makeLtHashGenerator(initialState);
166
// indexKey used to HMAC sign record.index.blob
167
// valueEncryptionKey used to AES-256-CBC encrypt record.value.blob[0:-32]
168
// the remaining record.value.blob[0:-32] is the mac, it the HMAC sign of key.keyId + decoded proto data + length of bytes in keyId
169
for (const msgMutation of msgMutations) {
170
// if it's a syncdmutation, get the operation property
171
// otherwise, if it's only a record -- it'll be a SET mutation
172
const operation = 'operation' in msgMutation ? msgMutation.operation : WAProto_1.proto.SyncdMutation.SyncdOperation.SET;
173
const record = ('record' in msgMutation && !!msgMutation.record) ? msgMutation.record : msgMutation;
174
const key = await getKey(record.keyId.id);
175
const content = Buffer.from(record.value.blob);
176
const encContent = content.slice(0, -32);
177
const ogValueMac = content.slice(-32);
178
if (validateMacs) {
179
const contentHmac = generateMac(operation, encContent, record.keyId.id, key.valueMacKey);
180
if (Buffer.compare(contentHmac, ogValueMac) !== 0) {
181
throw new boom_1.Boom('HMAC content verification failed');
182
}
183
}
184
const result = (0, crypto_1.aesDecrypt)(encContent, key.valueEncryptionKey);
185
const syncAction = WAProto_1.proto.SyncActionData.decode(result);
186
if (validateMacs) {
187
const hmac = (0, crypto_1.hmacSign)(syncAction.index, key.indexKey);
188
if (Buffer.compare(hmac, record.index.blob) !== 0) {
189
throw new boom_1.Boom('HMAC index verification failed');
190
}
191
}
192
const indexStr = Buffer.from(syncAction.index).toString();
193
onMutation({ syncAction, index: JSON.parse(indexStr) });
194
ltGenerator.mix({
195
indexMac: record.index.blob,
196
valueMac: ogValueMac,
197
operation: operation
198
});
199
}
200
return ltGenerator.finish();
201
};
202
exports.decodeSyncdMutations = decodeSyncdMutations;
203
const decodeSyncdPatch = async (msg, name, initialState, getAppStateSyncKey, onMutation, validateMacs) => {
204
if (validateMacs) {
205
const base64Key = Buffer.from(msg.keyId.id).toString('base64');
206
const mainKeyObj = await getAppStateSyncKey(base64Key);
207
const mainKey = mutationKeys(mainKeyObj.keyData);
208
const mutationmacs = msg.mutations.map(mutation => mutation.record.value.blob.slice(-32));
209
const patchMac = generatePatchMac(msg.snapshotMac, mutationmacs, (0, generics_1.toNumber)(msg.version.version), name, mainKey.patchMacKey);
210
if (Buffer.compare(patchMac, msg.patchMac) !== 0) {
211
throw new boom_1.Boom('Invalid patch mac');
212
}
213
}
214
const result = await (0, exports.decodeSyncdMutations)(msg.mutations, initialState, getAppStateSyncKey, onMutation, validateMacs);
215
return result;
216
};
217
exports.decodeSyncdPatch = decodeSyncdPatch;
218
const extractSyncdPatches = async (result) => {
219
const syncNode = (0, WABinary_1.getBinaryNodeChild)(result, 'sync');
220
const collectionNodes = (0, WABinary_1.getBinaryNodeChildren)(syncNode, 'collection');
221
const final = {};
222
await Promise.all(collectionNodes.map(async (collectionNode) => {
223
const patchesNode = (0, WABinary_1.getBinaryNodeChild)(collectionNode, 'patches');
224
const patches = (0, WABinary_1.getBinaryNodeChildren)(patchesNode || collectionNode, 'patch');
225
const snapshotNode = (0, WABinary_1.getBinaryNodeChild)(collectionNode, 'snapshot');
226
const syncds = [];
227
const name = collectionNode.attrs.name;
228
const hasMorePatches = collectionNode.attrs.has_more_patches === 'true';
229
let snapshot = undefined;
230
if (snapshotNode && !!snapshotNode.content) {
231
if (!Buffer.isBuffer(snapshotNode)) {
232
snapshotNode.content = Buffer.from(Object.values(snapshotNode.content));
233
}
234
const blobRef = WAProto_1.proto.ExternalBlobReference.decode(snapshotNode.content);
235
const data = await (0, exports.downloadExternalBlob)(blobRef);
236
snapshot = WAProto_1.proto.SyncdSnapshot.decode(data);
237
}
238
for (let { content } of patches) {
239
if (content) {
240
if (!Buffer.isBuffer(content)) {
241
content = Buffer.from(Object.values(content));
242
}
243
const syncd = WAProto_1.proto.SyncdPatch.decode(content);
244
if (!syncd.version) {
245
syncd.version = { version: +collectionNode.attrs.version + 1 };
246
}
247
syncds.push(syncd);
248
}
249
}
250
final[name] = { patches: syncds, hasMorePatches, snapshot };
251
}));
252
return final;
253
};
254
exports.extractSyncdPatches = extractSyncdPatches;
255
const downloadExternalBlob = async (blob) => {
256
const stream = await (0, messages_media_1.downloadContentFromMessage)(blob, 'md-app-state');
257
let buffer = Buffer.from([]);
258
for await (const chunk of stream) {
259
buffer = Buffer.concat([buffer, chunk]);
260
}
261
return buffer;
262
};
263
exports.downloadExternalBlob = downloadExternalBlob;
264
const downloadExternalPatch = async (blob) => {
265
const buffer = await (0, exports.downloadExternalBlob)(blob);
266
const syncData = WAProto_1.proto.SyncdMutations.decode(buffer);
267
return syncData;
268
};
269
exports.downloadExternalPatch = downloadExternalPatch;
270
const decodeSyncdSnapshot = async (name, snapshot, getAppStateSyncKey, minimumVersionNumber, onMutation, validateMacs = true) => {
271
const newState = (0, exports.newLTHashState)();
272
newState.version = (0, generics_1.toNumber)(snapshot.version.version);
273
onMutation = onMutation || (() => { });
274
const { hash, indexValueMap } = await (0, exports.decodeSyncdMutations)(snapshot.records, newState, getAppStateSyncKey, mutation => {
275
if (onMutation) {
276
const areMutationsRequired = typeof minimumVersionNumber === 'undefined' || newState.version > minimumVersionNumber;
277
if (areMutationsRequired) {
278
onMutation(mutation);
279
}
280
}
281
}, validateMacs);
282
newState.hash = hash;
283
newState.indexValueMap = indexValueMap;
284
if (validateMacs) {
285
const base64Key = Buffer.from(snapshot.keyId.id).toString('base64');
286
const keyEnc = await getAppStateSyncKey(base64Key);
287
if (!keyEnc) {
288
throw new boom_1.Boom(`failed to find key "${base64Key}" to decode mutation`, { statusCode: 500 });
289
}
290
const result = mutationKeys(keyEnc.keyData);
291
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey);
292
if (Buffer.compare(snapshot.mac, computedSnapshotMac) !== 0) {
293
throw new boom_1.Boom(`failed to verify LTHash at ${newState.version} of ${name} from snapshot`, { statusCode: 500 });
294
}
295
}
296
return {
297
state: newState,
298
};
299
};
300
exports.decodeSyncdSnapshot = decodeSyncdSnapshot;
301
const decodePatches = async (name, syncds, initial, getAppStateSyncKey, onMutation, minimumVersionNumber, logger, validateMacs = true) => {
302
var _a;
303
syncds = [...syncds];
304
const successfulMutations = [];
305
const newState = {
306
...initial,
307
indexValueMap: { ...initial.indexValueMap }
308
};
309
while (syncds.length) {
310
const syncd = syncds[0];
311
const { version, keyId, snapshotMac } = syncd;
312
if (syncd.externalMutations) {
313
logger === null || logger === void 0 ? void 0 : logger.trace({ name, version }, 'downloading external patch');
314
const ref = await (0, exports.downloadExternalPatch)(syncd.externalMutations);
315
logger === null || logger === void 0 ? void 0 : logger.debug({ name, version, mutations: ref.mutations.length }, 'downloaded external patch');
316
(_a = syncd.mutations) === null || _a === void 0 ? void 0 : _a.push(...ref.mutations);
317
}
318
const patchVersion = (0, generics_1.toNumber)(version.version);
319
newState.version = patchVersion;
320
const shouldMutate = typeof minimumVersionNumber === 'undefined' || patchVersion > minimumVersionNumber;
321
const decodeResult = await (0, exports.decodeSyncdPatch)(syncd, name, newState, getAppStateSyncKey, shouldMutate ? onMutation : (() => { }), validateMacs);
322
newState.hash = decodeResult.hash;
323
newState.indexValueMap = decodeResult.indexValueMap;
324
if (validateMacs) {
325
const base64Key = Buffer.from(keyId.id).toString('base64');
326
const keyEnc = await getAppStateSyncKey(base64Key);
327
if (!keyEnc) {
328
throw new boom_1.Boom(`failed to find key "${base64Key}" to decode mutation`);
329
}
330
const result = mutationKeys(keyEnc.keyData);
331
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey);
332
if (Buffer.compare(snapshotMac, computedSnapshotMac) !== 0) {
333
throw new boom_1.Boom(`failed to verify LTHash at ${newState.version} of ${name}`);
334
}
335
}
336
// clear memory used up by the mutations
337
syncd.mutations = [];
338
// pop first element
339
syncds.splice(0, 1);
340
}
341
return {
342
newMutations: successfulMutations,
343
state: newState
344
};
345
};
346
exports.decodePatches = decodePatches;
347
const chatModificationToAppPatch = (mod, jid) => {
348
const OP = WAProto_1.proto.SyncdMutation.SyncdOperation;
349
const getMessageRange = (lastMessages) => {
350
let messageRange;
351
if (Array.isArray(lastMessages)) {
352
const lastMsg = lastMessages[lastMessages.length - 1];
353
messageRange = {
354
lastMessageTimestamp: lastMsg === null || lastMsg === void 0 ? void 0 : lastMsg.messageTimestamp,
355
messages: (lastMessages === null || lastMessages === void 0 ? void 0 : lastMessages.length) ? lastMessages.map(m => {
356
var _a, _b;
357
if (!((_a = m.key) === null || _a === void 0 ? void 0 : _a.id) || !((_b = m.key) === null || _b === void 0 ? void 0 : _b.remoteJid)) {
358
throw new boom_1.Boom('Incomplete key', { statusCode: 400, data: m });
359
}
360
if ((0, WABinary_1.isJidGroup)(m.key.remoteJid) && !m.key.fromMe && !m.key.participant) {
361
throw new boom_1.Boom('Expected not from me message to have participant', { statusCode: 400, data: m });
362
}
363
if (!m.messageTimestamp || !(0, generics_1.toNumber)(m.messageTimestamp)) {
364
throw new boom_1.Boom('Missing timestamp in last message list', { statusCode: 400, data: m });
365
}
366
if (m.key.participant) {
367
m.key.participant = (0, WABinary_1.jidNormalizedUser)(m.key.participant);
368
}
369
return m;
370
}) : undefined
371
};
372
}
373
else {
374
messageRange = lastMessages;
375
}
376
return messageRange;
377
};
378
let patch;
379
if ('mute' in mod) {
380
patch = {
381
syncAction: {
382
muteAction: {
383
muted: !!mod.mute,
384
muteEndTimestamp: mod.mute || undefined
385
}
386
},
387
index: ['mute', jid],
388
type: 'regular_high',
389
apiVersion: 2,
390
operation: OP.SET
391
};
392
}
393
else if ('archive' in mod) {
394
patch = {
395
syncAction: {
396
archiveChatAction: {
397
archived: !!mod.archive,
398
messageRange: getMessageRange(mod.lastMessages)
399
}
400
},
401
index: ['archive', jid],
402
type: 'regular_low',
403
apiVersion: 3,
404
operation: OP.SET
405
};
406
}
407
else if ('markRead' in mod) {
408
patch = {
409
syncAction: {
410
markChatAsReadAction: {
411
read: mod.markRead,
412
messageRange: getMessageRange(mod.lastMessages)
413
}
414
},
415
index: ['markChatAsRead', jid],
416
type: 'regular_low',
417
apiVersion: 3,
418
operation: OP.SET
419
};
420
}
421
else if ('clear' in mod) {
422
if (mod.clear === 'all') {
423
throw new boom_1.Boom('not supported');
424
}
425
else {
426
const key = mod.clear.messages[0];
427
patch = {
428
syncAction: {
429
deleteMessageForMeAction: {
430
deleteMedia: false,
431
messageTimestamp: key.timestamp
432
}
433
},
434
index: ['deleteMessageForMe', jid, key.id, key.fromMe ? '1' : '0', '0'],
435
type: 'regular_high',
436
apiVersion: 3,
437
operation: OP.SET
438
};
439
}
440
}
441
else if ('pin' in mod) {
442
patch = {
443
syncAction: {
444
pinAction: {
445
pinned: !!mod.pin
446
}
447
},
448
index: ['pin_v1', jid],
449
type: 'regular_low',
450
apiVersion: 5,
451
operation: OP.SET
452
};
453
}
454
else if ('delete' in mod) {
455
patch = {
456
syncAction: {
457
deleteChatAction: {
458
messageRange: getMessageRange(mod.lastMessages),
459
}
460
},
461
index: ['deleteChat', jid, '1'],
462
type: 'regular_high',
463
apiVersion: 6,
464
operation: OP.SET
465
};
466
}
467
else if ('pushNameSetting' in mod) {
468
patch = {
469
syncAction: {
470
pushNameSetting: {
471
name: mod.pushNameSetting
472
}
473
},
474
index: ['setting_pushName'],
475
type: 'critical_block',
476
apiVersion: 1,
477
operation: OP.SET,
478
};
479
}
480
else {
481
throw new boom_1.Boom('not supported');
482
}
483
patch.syncAction.timestamp = Date.now();
484
return patch;
485
};
486
exports.chatModificationToAppPatch = chatModificationToAppPatch;
487
const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
488
var _a, _b, _c, _d, _e, _f;
489
const isInitialSync = !!initialSyncOpts;
490
const recvChats = initialSyncOpts === null || initialSyncOpts === void 0 ? void 0 : initialSyncOpts.recvChats;
491
const accountSettings = initialSyncOpts === null || initialSyncOpts === void 0 ? void 0 : initialSyncOpts.accountSettings;
492
const { syncAction: { value: action }, index: [type, id, msgId, fromMe] } = syncAction;
493
if (action === null || action === void 0 ? void 0 : action.muteAction) {
494
ev.emit('chats.update', [
495
{
496
id,
497
mute: ((_a = action.muteAction) === null || _a === void 0 ? void 0 : _a.muted) ?
498
(0, generics_1.toNumber)(action.muteAction.muteEndTimestamp) :
499
null
500
}
501
]);
502
}
503
else if (action === null || action === void 0 ? void 0 : action.archiveChatAction) {
504
// okay so we've to do some annoying computation here
505
// when we're initially syncing the app state
506
// there are a few cases we need to handle
507
// 1. if the account unarchiveChats setting is true
508
// a. if the chat is archived, and no further messages have been received -- simple, keep archived
509
// b. if the chat was archived, and the user received messages from the other person afterwards
510
// then the chat should be marked unarchved --
511
// we compare the timestamp of latest message from the other person to determine this
512
// 2. if the account unarchiveChats setting is false -- then it doesn't matter,
513
// it'll always take an app state action to mark in unarchived -- which we'll get anyway
514
const archiveAction = action.archiveChatAction;
515
if (isValidPatchBasedOnMessageRange(id, archiveAction.messageRange)
516
|| !isInitialSync
517
|| !(accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.unarchiveChats)) {
518
// basically we don't need to fire an "archive" update if the chat is being marked unarchvied
519
// this only applies for the initial sync
520
if (isInitialSync && !archiveAction.archived) {
521
ev.emit('chats.update', [{ id, archive: false }]);
522
}
523
else {
524
ev.emit('chats.update', [{ id, archive: !!(archiveAction === null || archiveAction === void 0 ? void 0 : archiveAction.archived) }]);
525
}
526
}
527
}
528
else if (action === null || action === void 0 ? void 0 : action.markChatAsReadAction) {
529
const markReadAction = action.markChatAsReadAction;
530
if (isValidPatchBasedOnMessageRange(id, markReadAction.messageRange)
531
|| !isInitialSync) {
532
// basically we don't need to fire an "read" update if the chat is being marked as read
533
// because the chat is read by default
534
// this only applies for the initial sync
535
if (isInitialSync && markReadAction.read) {
536
ev.emit('chats.update', [{ id, unreadCount: null }]);
537
}
538
else {
539
ev.emit('chats.update', [{ id, unreadCount: !!(markReadAction === null || markReadAction === void 0 ? void 0 : markReadAction.read) ? 0 : -1 }]);
540
}
541
}
542
}
543
else if ((action === null || action === void 0 ? void 0 : action.deleteMessageForMeAction) || type === 'deleteMessageForMe') {
544
ev.emit('messages.delete', { keys: [
545
{
546
remoteJid: id,
547
id: msgId,
548
fromMe: fromMe === '1'
549
}
550
] });
551
}
552
else if (action === null || action === void 0 ? void 0 : action.contactAction) {
553
ev.emit('contacts.upsert', [{ id, name: action.contactAction.fullName }]);
554
}
555
else if (action === null || action === void 0 ? void 0 : action.pushNameSetting) {
556
if ((me === null || me === void 0 ? void 0 : me.name) !== (action === null || action === void 0 ? void 0 : action.pushNameSetting)) {
557
ev.emit('creds.update', { me: { ...me, name: (_b = action === null || action === void 0 ? void 0 : action.pushNameSetting) === null || _b === void 0 ? void 0 : _b.name } });
558
}
559
}
560
else if (action === null || action === void 0 ? void 0 : action.pinAction) {
561
ev.emit('chats.update', [{ id, pin: ((_c = action.pinAction) === null || _c === void 0 ? void 0 : _c.pinned) ? (0, generics_1.toNumber)(action.timestamp) : null }]);
562
}
563
else if (action === null || action === void 0 ? void 0 : action.unarchiveChatsSetting) {
564
const unarchiveChats = !!action.unarchiveChatsSetting.unarchiveChats;
565
ev.emit('creds.update', { accountSettings: { unarchiveChats } });
566
logger === null || logger === void 0 ? void 0 : logger.info(`archive setting updated => '${action.unarchiveChatsSetting.unarchiveChats}'`);
567
if (accountSettings) {
568
accountSettings.unarchiveChats = unarchiveChats;
569
}
570
}
571
else if ((action === null || action === void 0 ? void 0 : action.starAction) || type === 'star') {
572
let starred = (_d = action === null || action === void 0 ? void 0 : action.starAction) === null || _d === void 0 ? void 0 : _d.starred;
573
if (typeof starred !== 'boolean') {
574
starred = syncAction.index[syncAction.index.length - 1] === '1';
575
}
576
ev.emit('messages.update', [
577
{
578
key: { remoteJid: id, id: msgId, fromMe: fromMe === '1' },
579
update: { starred }
580
}
581
]);
582
}
583
else if ((action === null || action === void 0 ? void 0 : action.deleteChatAction) || type === 'deleteChat') {
584
if ((((_e = action === null || action === void 0 ? void 0 : action.deleteChatAction) === null || _e === void 0 ? void 0 : _e.messageRange)
585
&& isValidPatchBasedOnMessageRange(id, (_f = action === null || action === void 0 ? void 0 : action.deleteChatAction) === null || _f === void 0 ? void 0 : _f.messageRange))
586
|| !isInitialSync) {
587
ev.emit('chats.delete', [id]);
588
}
589
}
590
else {
591
logger === null || logger === void 0 ? void 0 : logger.warn({ syncAction, id }, 'unprocessable update');
592
}
593
function isValidPatchBasedOnMessageRange(id, msgRange) {
594
const chat = recvChats === null || recvChats === void 0 ? void 0 : recvChats[id];
595
const lastMsgTimestamp = (msgRange === null || msgRange === void 0 ? void 0 : msgRange.lastMessageTimestamp) || (msgRange === null || msgRange === void 0 ? void 0 : msgRange.lastSystemMessageTimestamp) || 0;
596
const chatLastMsgTimestamp = (chat === null || chat === void 0 ? void 0 : chat.lastMsgRecvTimestamp) || 0;
597
return lastMsgTimestamp >= chatLastMsgTimestamp;
598
}
599
};
600
exports.processSyncAction = processSyncAction;
601
602