@baileys-md/baileys 10.1.0 → 11.0.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/LICENSE +1 -1
- package/README.md +1303 -2
- package/WAProto/GenerateStatics.sh +3 -0
- package/WAProto/WAProto.proto +4633 -0
- package/WAProto/fix-imports.js +29 -0
- package/WAProto/index.js +13516 -4182
- package/lib/Defaults/baileys-version.js +1 -0
- package/lib/Defaults/index.js +51 -72
- package/lib/Signal/Group/ciphertext-message.js +12 -0
- package/lib/Signal/Group/group-session-builder.js +30 -0
- package/lib/Signal/Group/group_cipher.js +94 -0
- package/lib/Signal/Group/index.js +12 -0
- package/lib/Signal/Group/keyhelper.js +19 -0
- package/lib/Signal/Group/queue-job.js +54 -0
- package/lib/Signal/Group/sender-chain-key.js +32 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +63 -0
- package/lib/Signal/Group/sender-key-message.js +67 -0
- package/lib/Signal/Group/sender-key-name.js +48 -0
- package/lib/Signal/Group/sender-key-record.js +50 -0
- package/lib/Signal/Group/sender-key-state.js +96 -0
- package/{WASignalGroup/sender_message_key.js → lib/Signal/Group/sender-message-key.js} +4 -16
- package/lib/Signal/libsignal.js +41 -61
- package/lib/Socket/Client/index.js +3 -19
- package/lib/Socket/Client/types.js +11 -0
- package/lib/Socket/Client/websocket.js +50 -0
- package/lib/Socket/business.js +37 -42
- package/lib/Socket/chats.js +194 -187
- package/lib/Socket/communities.js +351 -0
- package/lib/Socket/groups.js +87 -90
- package/lib/Socket/index.js +7 -8
- package/lib/Socket/messages-recv.js +360 -335
- package/lib/Socket/messages-send.js +156 -279
- package/lib/Socket/mex.js +42 -0
- package/lib/Socket/newsletter.js +144 -213
- package/lib/Socket/socket.js +128 -161
- package/lib/Socket/usync.js +19 -26
- package/lib/Types/Auth.js +2 -2
- package/lib/Types/Call.js +2 -2
- package/lib/Types/Chat.js +8 -4
- package/lib/Types/Contact.js +2 -2
- package/lib/Types/Events.js +2 -2
- package/lib/Types/GroupMetadata.js +2 -2
- package/lib/Types/Label.js +3 -5
- package/lib/Types/LabelAssociation.js +3 -5
- package/lib/Types/Message.js +7 -7
- package/lib/Types/Newsletter.js +30 -17
- package/lib/Types/Product.js +2 -2
- package/lib/Types/Signal.js +2 -2
- package/lib/Types/Socket.js +3 -2
- package/lib/Types/State.js +2 -2
- package/lib/Types/USync.js +2 -2
- package/lib/Types/index.js +15 -31
- package/lib/Utils/auth-utils.js +31 -47
- package/lib/Utils/baileys-event-stream.js +15 -22
- package/lib/Utils/business.js +66 -69
- package/lib/Utils/chat-utils.js +200 -195
- package/lib/Utils/crypto.js +70 -85
- package/lib/Utils/decode-wa-message.js +47 -51
- package/lib/Utils/event-buffer.js +36 -46
- package/lib/Utils/generics.js +116 -188
- package/lib/Utils/history.js +37 -46
- package/lib/Utils/index.js +19 -33
- package/lib/Utils/link-preview.js +14 -55
- package/lib/Utils/logger.js +3 -7
- package/lib/Utils/lt-hash.js +23 -26
- package/lib/{Store → Utils}/make-in-memory-store.js +19 -27
- package/lib/Utils/make-mutex.js +7 -10
- package/lib/{Store → Utils}/make-ordered-dictionary.js +1 -3
- package/lib/Utils/messages-media.js +236 -368
- package/lib/Utils/messages.js +278 -510
- package/lib/Utils/noise-handler.js +22 -31
- package/lib/{Store → Utils}/object-repository.js +1 -4
- package/lib/Utils/process-message.js +144 -148
- package/lib/Utils/signal.js +71 -64
- package/lib/Utils/use-multi-file-auth-state.js +112 -84
- package/lib/Utils/validate-connection.js +72 -115
- package/lib/WABinary/constants.js +1281 -20
- package/lib/WABinary/decode.js +15 -52
- package/lib/WABinary/encode.js +14 -48
- package/lib/WABinary/generic-utils.js +31 -39
- package/lib/WABinary/index.js +6 -21
- package/lib/WABinary/jid-utils.js +23 -40
- package/lib/WABinary/types.js +2 -2
- package/lib/WAM/BinaryInfo.js +2 -5
- package/lib/WAM/constants.js +2257 -2366
- package/lib/WAM/encode.js +17 -21
- package/lib/WAM/index.js +4 -19
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +8 -11
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +11 -14
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +9 -12
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +9 -13
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +20 -22
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +3 -6
- package/lib/WAUSync/Protocols/index.js +5 -20
- package/lib/WAUSync/USyncQuery.js +34 -32
- package/lib/WAUSync/USyncUser.js +2 -5
- package/lib/WAUSync/index.js +4 -19
- package/lib/index.js +11 -33
- package/package.json +25 -54
- package/WASignalGroup/GroupProtocol.js +0 -1697
- package/WASignalGroup/ciphertext_message.js +0 -16
- package/WASignalGroup/group_cipher.js +0 -120
- package/WASignalGroup/group_session_builder.js +0 -46
- package/WASignalGroup/index.js +0 -5
- package/WASignalGroup/keyhelper.js +0 -21
- package/WASignalGroup/protobufs.js +0 -3
- package/WASignalGroup/queue_job.js +0 -69
- package/WASignalGroup/sender_chain_key.js +0 -50
- package/WASignalGroup/sender_key_distribution_message.js +0 -78
- package/WASignalGroup/sender_key_message.js +0 -92
- package/WASignalGroup/sender_key_name.js +0 -70
- package/WASignalGroup/sender_key_record.js +0 -56
- package/WASignalGroup/sender_key_state.js +0 -129
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Socket/Client/abstract-socket-client.js +0 -13
- package/lib/Socket/Client/mobile-socket-client.js +0 -65
- package/lib/Socket/Client/web-socket-client.js +0 -62
- package/lib/Socket/registration.js +0 -166
- package/lib/Store/index.js +0 -8
- package/lib/Store/make-cache-manager-store.js +0 -83
- package/lib/Store/make-mongo-store.js +0 -567
package/lib/Utils/chat-utils.js
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const generics_1 = require("./generics");
|
|
10
|
-
const lt_hash_1 = require("./lt-hash");
|
|
11
|
-
const messages_media_1 = require("./messages-media");
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { proto } from '../../WAProto/index.js';
|
|
3
|
+
import { LabelAssociationType } from '../Types/LabelAssociation.js';
|
|
4
|
+
import { getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, isJidUser, jidNormalizedUser } from '../WABinary/index.js';
|
|
5
|
+
import { aesDecrypt, aesEncrypt, hkdf, hmacSign } from './crypto.js';
|
|
6
|
+
import { toNumber } from './generics.js';
|
|
7
|
+
import { LT_HASH_ANTI_TAMPERING } from './lt-hash.js';
|
|
8
|
+
import { downloadContentFromMessage } from './messages-media.js';
|
|
12
9
|
const mutationKeys = async (keydata) => {
|
|
13
|
-
const expanded = await
|
|
10
|
+
const expanded = await hkdf(keydata, 160, { info: 'WhatsApp Mutation Keys' });
|
|
14
11
|
return {
|
|
15
12
|
indexKey: expanded.slice(0, 32),
|
|
16
13
|
valueEncryptionKey: expanded.slice(32, 64),
|
|
@@ -23,10 +20,10 @@ const generateMac = (operation, data, keyId, key) => {
|
|
|
23
20
|
const getKeyData = () => {
|
|
24
21
|
let r;
|
|
25
22
|
switch (operation) {
|
|
26
|
-
case
|
|
23
|
+
case proto.SyncdMutation.SyncdOperation.SET:
|
|
27
24
|
r = 0x01;
|
|
28
25
|
break;
|
|
29
|
-
case
|
|
26
|
+
case proto.SyncdMutation.SyncdOperation.REMOVE:
|
|
30
27
|
r = 0x02;
|
|
31
28
|
break;
|
|
32
29
|
}
|
|
@@ -37,7 +34,7 @@ const generateMac = (operation, data, keyId, key) => {
|
|
|
37
34
|
const last = Buffer.alloc(8); // 8 bytes
|
|
38
35
|
last.set([keyData.length], last.length - 1);
|
|
39
36
|
const total = Buffer.concat([keyData, data, last]);
|
|
40
|
-
const hmac =
|
|
37
|
+
const hmac = hmacSign(total, key, 'sha512');
|
|
41
38
|
return hmac.slice(0, 32);
|
|
42
39
|
};
|
|
43
40
|
const to64BitNetworkOrder = (e) => {
|
|
@@ -53,9 +50,9 @@ const makeLtHashGenerator = ({ indexValueMap, hash }) => {
|
|
|
53
50
|
mix: ({ indexMac, valueMac, operation }) => {
|
|
54
51
|
const indexMacBase64 = Buffer.from(indexMac).toString('base64');
|
|
55
52
|
const prevOp = indexValueMap[indexMacBase64];
|
|
56
|
-
if (operation ===
|
|
53
|
+
if (operation === proto.SyncdMutation.SyncdOperation.REMOVE) {
|
|
57
54
|
if (!prevOp) {
|
|
58
|
-
throw new
|
|
55
|
+
throw new Boom('tried remove, but no previous op', { data: { indexMac, valueMac } });
|
|
59
56
|
}
|
|
60
57
|
// remove from index value mac, since this mutation is erased
|
|
61
58
|
delete indexValueMap[indexMacBase64];
|
|
@@ -71,7 +68,7 @@ const makeLtHashGenerator = ({ indexValueMap, hash }) => {
|
|
|
71
68
|
},
|
|
72
69
|
finish: async () => {
|
|
73
70
|
const hashArrayBuffer = new Uint8Array(hash).buffer;
|
|
74
|
-
const result = await
|
|
71
|
+
const result = await LT_HASH_ANTI_TAMPERING.subtractThenAdd(hashArrayBuffer, addBuffs, subBuffs);
|
|
75
72
|
const buffer = Buffer.from(result);
|
|
76
73
|
return {
|
|
77
74
|
hash: buffer,
|
|
@@ -81,43 +78,33 @@ const makeLtHashGenerator = ({ indexValueMap, hash }) => {
|
|
|
81
78
|
};
|
|
82
79
|
};
|
|
83
80
|
const generateSnapshotMac = (lthash, version, name, key) => {
|
|
84
|
-
const total = Buffer.concat([
|
|
85
|
-
|
|
86
|
-
to64BitNetworkOrder(version),
|
|
87
|
-
Buffer.from(name, 'utf-8')
|
|
88
|
-
]);
|
|
89
|
-
return (0, crypto_1.hmacSign)(total, key, 'sha256');
|
|
81
|
+
const total = Buffer.concat([lthash, to64BitNetworkOrder(version), Buffer.from(name, 'utf-8')]);
|
|
82
|
+
return hmacSign(total, key, 'sha256');
|
|
90
83
|
};
|
|
91
84
|
const generatePatchMac = (snapshotMac, valueMacs, version, type, key) => {
|
|
92
|
-
const total = Buffer.concat([
|
|
93
|
-
|
|
94
|
-
...valueMacs,
|
|
95
|
-
to64BitNetworkOrder(version),
|
|
96
|
-
Buffer.from(type, 'utf-8')
|
|
97
|
-
]);
|
|
98
|
-
return (0, crypto_1.hmacSign)(total, key);
|
|
85
|
+
const total = Buffer.concat([snapshotMac, ...valueMacs, to64BitNetworkOrder(version), Buffer.from(type, 'utf-8')]);
|
|
86
|
+
return hmacSign(total, key);
|
|
99
87
|
};
|
|
100
|
-
const newLTHashState = () => ({ version: 0, hash: Buffer.alloc(128), indexValueMap: {} });
|
|
101
|
-
|
|
102
|
-
const encodeSyncdPatch = async ({ type, index, syncAction, apiVersion, operation }, myAppStateKeyId, state, getAppStateSyncKey) => {
|
|
88
|
+
export const newLTHashState = () => ({ version: 0, hash: Buffer.alloc(128), indexValueMap: {} });
|
|
89
|
+
export const encodeSyncdPatch = async ({ type, index, syncAction, apiVersion, operation }, myAppStateKeyId, state, getAppStateSyncKey) => {
|
|
103
90
|
const key = !!myAppStateKeyId ? await getAppStateSyncKey(myAppStateKeyId) : undefined;
|
|
104
91
|
if (!key) {
|
|
105
|
-
throw new
|
|
92
|
+
throw new Boom(`myAppStateKey ("${myAppStateKeyId}") not present`, { statusCode: 404 });
|
|
106
93
|
}
|
|
107
94
|
const encKeyId = Buffer.from(myAppStateKeyId, 'base64');
|
|
108
95
|
state = { ...state, indexValueMap: { ...state.indexValueMap } };
|
|
109
96
|
const indexBuffer = Buffer.from(JSON.stringify(index));
|
|
110
|
-
const dataProto =
|
|
97
|
+
const dataProto = proto.SyncActionData.fromObject({
|
|
111
98
|
index: indexBuffer,
|
|
112
99
|
value: syncAction,
|
|
113
100
|
padding: new Uint8Array(0),
|
|
114
101
|
version: apiVersion
|
|
115
102
|
});
|
|
116
|
-
const encoded =
|
|
103
|
+
const encoded = proto.SyncActionData.encode(dataProto).finish();
|
|
117
104
|
const keyValue = await mutationKeys(key.keyData);
|
|
118
|
-
const encValue =
|
|
105
|
+
const encValue = aesEncrypt(encoded, keyValue.valueEncryptionKey);
|
|
119
106
|
const valueMac = generateMac(operation, encValue, encKeyId, keyValue.valueMacKey);
|
|
120
|
-
const indexMac =
|
|
107
|
+
const indexMac = hmacSign(indexBuffer, keyValue.indexKey);
|
|
121
108
|
// update LT hash
|
|
122
109
|
const generator = makeLtHashGenerator(state);
|
|
123
110
|
generator.mix({ indexMac, valueMac, operation });
|
|
@@ -147,8 +134,7 @@ const encodeSyncdPatch = async ({ type, index, syncAction, apiVersion, operation
|
|
|
147
134
|
state.indexValueMap[base64Index] = { valueMac };
|
|
148
135
|
return { patch, state };
|
|
149
136
|
};
|
|
150
|
-
|
|
151
|
-
const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncKey, onMutation, validateMacs) => {
|
|
137
|
+
export const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncKey, onMutation, validateMacs) => {
|
|
152
138
|
const ltGenerator = makeLtHashGenerator(initialState);
|
|
153
139
|
// indexKey used to HMAC sign record.index.blob
|
|
154
140
|
// valueEncryptionKey used to AES-256-CBC encrypt record.value.blob[0:-32]
|
|
@@ -156,8 +142,8 @@ const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncK
|
|
|
156
142
|
for (const msgMutation of msgMutations) {
|
|
157
143
|
// if it's a syncdmutation, get the operation property
|
|
158
144
|
// otherwise, if it's only a record -- it'll be a SET mutation
|
|
159
|
-
const operation = 'operation' in msgMutation ? msgMutation.operation :
|
|
160
|
-
const record =
|
|
145
|
+
const operation = 'operation' in msgMutation ? msgMutation.operation : proto.SyncdMutation.SyncdOperation.SET;
|
|
146
|
+
const record = 'record' in msgMutation && !!msgMutation.record ? msgMutation.record : msgMutation;
|
|
161
147
|
const key = await getKey(record.keyId.id);
|
|
162
148
|
const content = Buffer.from(record.value.blob);
|
|
163
149
|
const encContent = content.slice(0, -32);
|
|
@@ -165,15 +151,15 @@ const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncK
|
|
|
165
151
|
if (validateMacs) {
|
|
166
152
|
const contentHmac = generateMac(operation, encContent, record.keyId.id, key.valueMacKey);
|
|
167
153
|
if (Buffer.compare(contentHmac, ogValueMac) !== 0) {
|
|
168
|
-
throw new
|
|
154
|
+
throw new Boom('HMAC content verification failed');
|
|
169
155
|
}
|
|
170
156
|
}
|
|
171
|
-
const result =
|
|
172
|
-
const syncAction =
|
|
157
|
+
const result = aesDecrypt(encContent, key.valueEncryptionKey);
|
|
158
|
+
const syncAction = proto.SyncActionData.decode(result);
|
|
173
159
|
if (validateMacs) {
|
|
174
|
-
const hmac =
|
|
160
|
+
const hmac = hmacSign(syncAction.index, key.indexKey);
|
|
175
161
|
if (Buffer.compare(hmac, record.index.blob) !== 0) {
|
|
176
|
-
throw new
|
|
162
|
+
throw new Boom('HMAC index verification failed');
|
|
177
163
|
}
|
|
178
164
|
}
|
|
179
165
|
const indexStr = Buffer.from(syncAction.index).toString();
|
|
@@ -189,38 +175,39 @@ const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncK
|
|
|
189
175
|
const base64Key = Buffer.from(keyId).toString('base64');
|
|
190
176
|
const keyEnc = await getAppStateSyncKey(base64Key);
|
|
191
177
|
if (!keyEnc) {
|
|
192
|
-
throw new
|
|
178
|
+
throw new Boom(`failed to find key "${base64Key}" to decode mutation`, {
|
|
179
|
+
statusCode: 404,
|
|
180
|
+
data: { msgMutations }
|
|
181
|
+
});
|
|
193
182
|
}
|
|
194
183
|
return mutationKeys(keyEnc.keyData);
|
|
195
184
|
}
|
|
196
185
|
};
|
|
197
|
-
|
|
198
|
-
const decodeSyncdPatch = async (msg, name, initialState, getAppStateSyncKey, onMutation, validateMacs) => {
|
|
186
|
+
export const decodeSyncdPatch = async (msg, name, initialState, getAppStateSyncKey, onMutation, validateMacs) => {
|
|
199
187
|
if (validateMacs) {
|
|
200
188
|
const base64Key = Buffer.from(msg.keyId.id).toString('base64');
|
|
201
189
|
const mainKeyObj = await getAppStateSyncKey(base64Key);
|
|
202
190
|
if (!mainKeyObj) {
|
|
203
|
-
throw new
|
|
191
|
+
throw new Boom(`failed to find key "${base64Key}" to decode patch`, { statusCode: 404, data: { msg } });
|
|
204
192
|
}
|
|
205
193
|
const mainKey = await mutationKeys(mainKeyObj.keyData);
|
|
206
194
|
const mutationmacs = msg.mutations.map(mutation => mutation.record.value.blob.slice(-32));
|
|
207
|
-
const patchMac = generatePatchMac(msg.snapshotMac, mutationmacs,
|
|
195
|
+
const patchMac = generatePatchMac(msg.snapshotMac, mutationmacs, toNumber(msg.version.version), name, mainKey.patchMacKey);
|
|
208
196
|
if (Buffer.compare(patchMac, msg.patchMac) !== 0) {
|
|
209
|
-
throw new
|
|
197
|
+
throw new Boom('Invalid patch mac');
|
|
210
198
|
}
|
|
211
199
|
}
|
|
212
|
-
const result = await
|
|
200
|
+
const result = await decodeSyncdMutations(msg.mutations, initialState, getAppStateSyncKey, onMutation, validateMacs);
|
|
213
201
|
return result;
|
|
214
202
|
};
|
|
215
|
-
|
|
216
|
-
const
|
|
217
|
-
const
|
|
218
|
-
const collectionNodes = (0, WABinary_1.getBinaryNodeChildren)(syncNode, 'collection');
|
|
203
|
+
export const extractSyncdPatches = async (result, options) => {
|
|
204
|
+
const syncNode = getBinaryNodeChild(result, 'sync');
|
|
205
|
+
const collectionNodes = getBinaryNodeChildren(syncNode, 'collection');
|
|
219
206
|
const final = {};
|
|
220
207
|
await Promise.all(collectionNodes.map(async (collectionNode) => {
|
|
221
|
-
const patchesNode =
|
|
222
|
-
const patches =
|
|
223
|
-
const snapshotNode =
|
|
208
|
+
const patchesNode = getBinaryNodeChild(collectionNode, 'patches');
|
|
209
|
+
const patches = getBinaryNodeChildren(patchesNode || collectionNode, 'patch');
|
|
210
|
+
const snapshotNode = getBinaryNodeChild(collectionNode, 'snapshot');
|
|
224
211
|
const syncds = [];
|
|
225
212
|
const name = collectionNode.attrs.name;
|
|
226
213
|
const hasMorePatches = collectionNode.attrs.has_more_patches === 'true';
|
|
@@ -229,16 +216,16 @@ const extractSyncdPatches = async (result, options) => {
|
|
|
229
216
|
if (!Buffer.isBuffer(snapshotNode)) {
|
|
230
217
|
snapshotNode.content = Buffer.from(Object.values(snapshotNode.content));
|
|
231
218
|
}
|
|
232
|
-
const blobRef =
|
|
233
|
-
const data = await
|
|
234
|
-
snapshot =
|
|
219
|
+
const blobRef = proto.ExternalBlobReference.decode(snapshotNode.content);
|
|
220
|
+
const data = await downloadExternalBlob(blobRef, options);
|
|
221
|
+
snapshot = proto.SyncdSnapshot.decode(data);
|
|
235
222
|
}
|
|
236
223
|
for (let { content } of patches) {
|
|
237
224
|
if (content) {
|
|
238
225
|
if (!Buffer.isBuffer(content)) {
|
|
239
226
|
content = Buffer.from(Object.values(content));
|
|
240
227
|
}
|
|
241
|
-
const syncd =
|
|
228
|
+
const syncd = proto.SyncdPatch.decode(content);
|
|
242
229
|
if (!syncd.version) {
|
|
243
230
|
syncd.version = { version: +collectionNode.attrs.version + 1 };
|
|
244
231
|
}
|
|
@@ -249,32 +236,27 @@ const extractSyncdPatches = async (result, options) => {
|
|
|
249
236
|
}));
|
|
250
237
|
return final;
|
|
251
238
|
};
|
|
252
|
-
|
|
253
|
-
const
|
|
254
|
-
const stream = await (0, messages_media_1.downloadContentFromMessage)(blob, 'md-app-state', { options });
|
|
239
|
+
export const downloadExternalBlob = async (blob, options) => {
|
|
240
|
+
const stream = await downloadContentFromMessage(blob, 'md-app-state', { options });
|
|
255
241
|
const bufferArray = [];
|
|
256
242
|
for await (const chunk of stream) {
|
|
257
243
|
bufferArray.push(chunk);
|
|
258
244
|
}
|
|
259
245
|
return Buffer.concat(bufferArray);
|
|
260
246
|
};
|
|
261
|
-
|
|
262
|
-
const
|
|
263
|
-
const
|
|
264
|
-
const syncData = WAProto_1.proto.SyncdMutations.decode(buffer);
|
|
247
|
+
export const downloadExternalPatch = async (blob, options) => {
|
|
248
|
+
const buffer = await downloadExternalBlob(blob, options);
|
|
249
|
+
const syncData = proto.SyncdMutations.decode(buffer);
|
|
265
250
|
return syncData;
|
|
266
251
|
};
|
|
267
|
-
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
newState.version = (0, generics_1.toNumber)(snapshot.version.version);
|
|
252
|
+
export const decodeSyncdSnapshot = async (name, snapshot, getAppStateSyncKey, minimumVersionNumber, validateMacs = true) => {
|
|
253
|
+
const newState = newLTHashState();
|
|
254
|
+
newState.version = toNumber(snapshot.version.version);
|
|
271
255
|
const mutationMap = {};
|
|
272
|
-
const areMutationsRequired = typeof minimumVersionNumber === 'undefined'
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
var _a;
|
|
277
|
-
const index = (_a = mutation.syncAction.index) === null || _a === void 0 ? void 0 : _a.toString();
|
|
256
|
+
const areMutationsRequired = typeof minimumVersionNumber === 'undefined' || newState.version > minimumVersionNumber;
|
|
257
|
+
const { hash, indexValueMap } = await decodeSyncdMutations(snapshot.records, newState, getAppStateSyncKey, areMutationsRequired
|
|
258
|
+
? mutation => {
|
|
259
|
+
const index = mutation.syncAction.index?.toString();
|
|
278
260
|
mutationMap[index] = mutation;
|
|
279
261
|
}
|
|
280
262
|
: () => { }, validateMacs);
|
|
@@ -284,12 +266,12 @@ const decodeSyncdSnapshot = async (name, snapshot, getAppStateSyncKey, minimumVe
|
|
|
284
266
|
const base64Key = Buffer.from(snapshot.keyId.id).toString('base64');
|
|
285
267
|
const keyEnc = await getAppStateSyncKey(base64Key);
|
|
286
268
|
if (!keyEnc) {
|
|
287
|
-
throw new
|
|
269
|
+
throw new Boom(`failed to find key "${base64Key}" to decode mutation`);
|
|
288
270
|
}
|
|
289
271
|
const result = await mutationKeys(keyEnc.keyData);
|
|
290
272
|
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey);
|
|
291
273
|
if (Buffer.compare(snapshot.mac, computedSnapshotMac) !== 0) {
|
|
292
|
-
throw new
|
|
274
|
+
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name} from snapshot`);
|
|
293
275
|
}
|
|
294
276
|
}
|
|
295
277
|
return {
|
|
@@ -297,45 +279,41 @@ const decodeSyncdSnapshot = async (name, snapshot, getAppStateSyncKey, minimumVe
|
|
|
297
279
|
mutationMap
|
|
298
280
|
};
|
|
299
281
|
};
|
|
300
|
-
|
|
301
|
-
const decodePatches = async (name, syncds, initial, getAppStateSyncKey, options, minimumVersionNumber, logger, validateMacs = true) => {
|
|
302
|
-
var _a;
|
|
282
|
+
export const decodePatches = async (name, syncds, initial, getAppStateSyncKey, options, minimumVersionNumber, logger, validateMacs = true) => {
|
|
303
283
|
const newState = {
|
|
304
284
|
...initial,
|
|
305
285
|
indexValueMap: { ...initial.indexValueMap }
|
|
306
286
|
};
|
|
307
287
|
const mutationMap = {};
|
|
308
|
-
for (
|
|
309
|
-
const syncd = syncds[i];
|
|
288
|
+
for (const syncd of syncds) {
|
|
310
289
|
const { version, keyId, snapshotMac } = syncd;
|
|
311
290
|
if (syncd.externalMutations) {
|
|
312
|
-
logger
|
|
313
|
-
const ref = await
|
|
314
|
-
logger
|
|
315
|
-
|
|
291
|
+
logger?.trace({ name, version }, 'downloading external patch');
|
|
292
|
+
const ref = await downloadExternalPatch(syncd.externalMutations, options);
|
|
293
|
+
logger?.debug({ name, version, mutations: ref.mutations.length }, 'downloaded external patch');
|
|
294
|
+
syncd.mutations?.push(...ref.mutations);
|
|
316
295
|
}
|
|
317
|
-
const patchVersion =
|
|
296
|
+
const patchVersion = toNumber(version.version);
|
|
318
297
|
newState.version = patchVersion;
|
|
319
298
|
const shouldMutate = typeof minimumVersionNumber === 'undefined' || patchVersion > minimumVersionNumber;
|
|
320
|
-
const decodeResult = await
|
|
299
|
+
const decodeResult = await decodeSyncdPatch(syncd, name, newState, getAppStateSyncKey, shouldMutate
|
|
321
300
|
? mutation => {
|
|
322
|
-
|
|
323
|
-
const index = (_a = mutation.syncAction.index) === null || _a === void 0 ? void 0 : _a.toString();
|
|
301
|
+
const index = mutation.syncAction.index?.toString();
|
|
324
302
|
mutationMap[index] = mutation;
|
|
325
303
|
}
|
|
326
|
-
: (
|
|
304
|
+
: () => { }, true);
|
|
327
305
|
newState.hash = decodeResult.hash;
|
|
328
306
|
newState.indexValueMap = decodeResult.indexValueMap;
|
|
329
307
|
if (validateMacs) {
|
|
330
308
|
const base64Key = Buffer.from(keyId.id).toString('base64');
|
|
331
309
|
const keyEnc = await getAppStateSyncKey(base64Key);
|
|
332
310
|
if (!keyEnc) {
|
|
333
|
-
throw new
|
|
311
|
+
throw new Boom(`failed to find key "${base64Key}" to decode mutation`);
|
|
334
312
|
}
|
|
335
313
|
const result = await mutationKeys(keyEnc.keyData);
|
|
336
314
|
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey);
|
|
337
315
|
if (Buffer.compare(snapshotMac, computedSnapshotMac) !== 0) {
|
|
338
|
-
throw new
|
|
316
|
+
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name}`);
|
|
339
317
|
}
|
|
340
318
|
}
|
|
341
319
|
// clear memory used up by the mutations
|
|
@@ -343,31 +321,31 @@ const decodePatches = async (name, syncds, initial, getAppStateSyncKey, options,
|
|
|
343
321
|
}
|
|
344
322
|
return { state: newState, mutationMap };
|
|
345
323
|
};
|
|
346
|
-
|
|
347
|
-
const
|
|
348
|
-
const OP = WAProto_1.proto.SyncdMutation.SyncdOperation;
|
|
324
|
+
export const chatModificationToAppPatch = (mod, jid) => {
|
|
325
|
+
const OP = proto.SyncdMutation.SyncdOperation;
|
|
349
326
|
const getMessageRange = (lastMessages) => {
|
|
350
327
|
let messageRange;
|
|
351
328
|
if (Array.isArray(lastMessages)) {
|
|
352
329
|
const lastMsg = lastMessages[lastMessages.length - 1];
|
|
353
330
|
messageRange = {
|
|
354
|
-
lastMessageTimestamp: lastMsg
|
|
355
|
-
messages:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
331
|
+
lastMessageTimestamp: lastMsg?.messageTimestamp,
|
|
332
|
+
messages: lastMessages?.length
|
|
333
|
+
? lastMessages.map(m => {
|
|
334
|
+
if (!m.key?.id || !m.key?.remoteJid) {
|
|
335
|
+
throw new Boom('Incomplete key', { statusCode: 400, data: m });
|
|
336
|
+
}
|
|
337
|
+
if (isJidGroup(m.key.remoteJid) && !m.key.fromMe && !m.key.participant) {
|
|
338
|
+
throw new Boom('Expected not from me message to have participant', { statusCode: 400, data: m });
|
|
339
|
+
}
|
|
340
|
+
if (!m.messageTimestamp || !toNumber(m.messageTimestamp)) {
|
|
341
|
+
throw new Boom('Missing timestamp in last message list', { statusCode: 400, data: m });
|
|
342
|
+
}
|
|
343
|
+
if (m.key.participant) {
|
|
344
|
+
m.key.participant = jidNormalizedUser(m.key.participant);
|
|
345
|
+
}
|
|
346
|
+
return m;
|
|
347
|
+
})
|
|
348
|
+
: undefined
|
|
371
349
|
};
|
|
372
350
|
}
|
|
373
351
|
else {
|
|
@@ -436,7 +414,9 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
436
414
|
else if ('clear' in mod) {
|
|
437
415
|
patch = {
|
|
438
416
|
syncAction: {
|
|
439
|
-
clearChatAction: {
|
|
417
|
+
clearChatAction: {
|
|
418
|
+
messageRange: getMessageRange(mod.lastMessages)
|
|
419
|
+
}
|
|
440
420
|
},
|
|
441
421
|
index: ['clearChat', jid, '1' /*the option here is 0 when keep starred messages is enabled*/, '0'],
|
|
442
422
|
type: 'regular_high',
|
|
@@ -457,6 +437,17 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
457
437
|
operation: OP.SET
|
|
458
438
|
};
|
|
459
439
|
}
|
|
440
|
+
else if ('contact' in mod) {
|
|
441
|
+
patch = {
|
|
442
|
+
syncAction: {
|
|
443
|
+
contactAction: mod.contact || {}
|
|
444
|
+
},
|
|
445
|
+
index: ['contact', jid],
|
|
446
|
+
type: 'critical_unblock_low',
|
|
447
|
+
apiVersion: 2,
|
|
448
|
+
operation: mod.contact ? OP.SET : OP.REMOVE
|
|
449
|
+
};
|
|
450
|
+
}
|
|
460
451
|
else if ('star' in mod) {
|
|
461
452
|
const key = mod.star.messages[0];
|
|
462
453
|
patch = {
|
|
@@ -475,7 +466,7 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
475
466
|
patch = {
|
|
476
467
|
syncAction: {
|
|
477
468
|
deleteChatAction: {
|
|
478
|
-
messageRange: getMessageRange(mod.lastMessages)
|
|
469
|
+
messageRange: getMessageRange(mod.lastMessages)
|
|
479
470
|
}
|
|
480
471
|
},
|
|
481
472
|
index: ['deleteChat', jid, '1'],
|
|
@@ -494,64 +485,73 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
494
485
|
index: ['setting_pushName'],
|
|
495
486
|
type: 'critical_block',
|
|
496
487
|
apiVersion: 1,
|
|
497
|
-
operation: OP.SET
|
|
488
|
+
operation: OP.SET
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
else if ('addLabel' in mod) {
|
|
492
|
+
patch = {
|
|
493
|
+
syncAction: {
|
|
494
|
+
labelEditAction: {
|
|
495
|
+
name: mod.addLabel.name,
|
|
496
|
+
color: mod.addLabel.color,
|
|
497
|
+
predefinedId: mod.addLabel.predefinedId,
|
|
498
|
+
deleted: mod.addLabel.deleted
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
index: ['label_edit', mod.addLabel.id],
|
|
502
|
+
type: 'regular',
|
|
503
|
+
apiVersion: 3,
|
|
504
|
+
operation: OP.SET
|
|
498
505
|
};
|
|
499
506
|
}
|
|
500
507
|
else if ('addChatLabel' in mod) {
|
|
501
508
|
patch = {
|
|
502
509
|
syncAction: {
|
|
503
510
|
labelAssociationAction: {
|
|
504
|
-
labeled: true
|
|
511
|
+
labeled: true
|
|
505
512
|
}
|
|
506
513
|
},
|
|
507
|
-
index: [
|
|
514
|
+
index: [LabelAssociationType.Chat, mod.addChatLabel.labelId, jid],
|
|
508
515
|
type: 'regular',
|
|
509
516
|
apiVersion: 3,
|
|
510
|
-
operation: OP.SET
|
|
517
|
+
operation: OP.SET
|
|
511
518
|
};
|
|
512
519
|
}
|
|
513
520
|
else if ('removeChatLabel' in mod) {
|
|
514
521
|
patch = {
|
|
515
522
|
syncAction: {
|
|
516
523
|
labelAssociationAction: {
|
|
517
|
-
labeled: false
|
|
524
|
+
labeled: false
|
|
518
525
|
}
|
|
519
526
|
},
|
|
520
|
-
index: [
|
|
527
|
+
index: [LabelAssociationType.Chat, mod.removeChatLabel.labelId, jid],
|
|
521
528
|
type: 'regular',
|
|
522
529
|
apiVersion: 3,
|
|
523
|
-
operation: OP.SET
|
|
530
|
+
operation: OP.SET
|
|
524
531
|
};
|
|
525
532
|
}
|
|
526
533
|
else if ('addMessageLabel' in mod) {
|
|
527
534
|
patch = {
|
|
528
535
|
syncAction: {
|
|
529
536
|
labelAssociationAction: {
|
|
530
|
-
labeled: true
|
|
537
|
+
labeled: true
|
|
531
538
|
}
|
|
532
539
|
},
|
|
533
|
-
index: [
|
|
534
|
-
LabelAssociation_1.LabelAssociationType.Message,
|
|
535
|
-
mod.addMessageLabel.labelId,
|
|
536
|
-
jid,
|
|
537
|
-
mod.addMessageLabel.messageId,
|
|
538
|
-
'0',
|
|
539
|
-
'0'
|
|
540
|
-
],
|
|
540
|
+
index: [LabelAssociationType.Message, mod.addMessageLabel.labelId, jid, mod.addMessageLabel.messageId, '0', '0'],
|
|
541
541
|
type: 'regular',
|
|
542
542
|
apiVersion: 3,
|
|
543
|
-
operation: OP.SET
|
|
543
|
+
operation: OP.SET
|
|
544
544
|
};
|
|
545
545
|
}
|
|
546
546
|
else if ('removeMessageLabel' in mod) {
|
|
547
547
|
patch = {
|
|
548
548
|
syncAction: {
|
|
549
549
|
labelAssociationAction: {
|
|
550
|
-
labeled: false
|
|
550
|
+
labeled: false
|
|
551
551
|
}
|
|
552
552
|
},
|
|
553
553
|
index: [
|
|
554
|
-
|
|
554
|
+
LabelAssociationType.Message,
|
|
555
555
|
mod.removeMessageLabel.labelId,
|
|
556
556
|
jid,
|
|
557
557
|
mod.removeMessageLabel.messageId,
|
|
@@ -560,34 +560,30 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
560
560
|
],
|
|
561
561
|
type: 'regular',
|
|
562
562
|
apiVersion: 3,
|
|
563
|
-
operation: OP.SET
|
|
563
|
+
operation: OP.SET
|
|
564
564
|
};
|
|
565
565
|
}
|
|
566
566
|
else {
|
|
567
|
-
throw new
|
|
567
|
+
throw new Boom('not supported');
|
|
568
568
|
}
|
|
569
569
|
patch.syncAction.timestamp = Date.now();
|
|
570
570
|
return patch;
|
|
571
571
|
};
|
|
572
|
-
|
|
573
|
-
const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
574
|
-
var _a, _b, _c, _d;
|
|
572
|
+
export const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
575
573
|
const isInitialSync = !!initialSyncOpts;
|
|
576
|
-
const accountSettings = initialSyncOpts
|
|
577
|
-
logger
|
|
574
|
+
const accountSettings = initialSyncOpts?.accountSettings;
|
|
575
|
+
logger?.trace({ syncAction, initialSync: !!initialSyncOpts }, 'processing sync action');
|
|
578
576
|
const { syncAction: { value: action }, index: [type, id, msgId, fromMe] } = syncAction;
|
|
579
|
-
if (action
|
|
577
|
+
if (action?.muteAction) {
|
|
580
578
|
ev.emit('chats.update', [
|
|
581
579
|
{
|
|
582
580
|
id,
|
|
583
|
-
muteEndTime:
|
|
584
|
-
? (0, generics_1.toNumber)(action.muteAction.muteEndTimestamp)
|
|
585
|
-
: null,
|
|
581
|
+
muteEndTime: action.muteAction?.muted ? toNumber(action.muteAction.muteEndTimestamp) : null,
|
|
586
582
|
conditional: getChatUpdateConditional(id, undefined)
|
|
587
583
|
}
|
|
588
584
|
]);
|
|
589
585
|
}
|
|
590
|
-
else if (
|
|
586
|
+
else if (action?.archiveChatAction || type === 'archive' || type === 'unarchive') {
|
|
591
587
|
// okay so we've to do some annoying computation here
|
|
592
588
|
// when we're initially syncing the app state
|
|
593
589
|
// there are a few cases we need to handle
|
|
@@ -598,36 +594,38 @@ const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
|
598
594
|
// we compare the timestamp of latest message from the other person to determine this
|
|
599
595
|
// 2. if the account unarchiveChats setting is false -- then it doesn't matter,
|
|
600
596
|
// it'll always take an app state action to mark in unarchived -- which we'll get anyway
|
|
601
|
-
const archiveAction = action
|
|
602
|
-
const isArchived = archiveAction
|
|
603
|
-
? archiveAction.archived
|
|
604
|
-
: type === 'archive';
|
|
597
|
+
const archiveAction = action?.archiveChatAction;
|
|
598
|
+
const isArchived = archiveAction ? archiveAction.archived : type === 'archive';
|
|
605
599
|
// // basically we don't need to fire an "archive" update if the chat is being marked unarchvied
|
|
606
600
|
// // this only applies for the initial sync
|
|
607
601
|
// if(isInitialSync && !isArchived) {
|
|
608
602
|
// isArchived = false
|
|
609
603
|
// }
|
|
610
|
-
const msgRange = !
|
|
604
|
+
const msgRange = !accountSettings?.unarchiveChats ? undefined : archiveAction?.messageRange;
|
|
611
605
|
// logger?.debug({ chat: id, syncAction }, 'message range archive')
|
|
612
|
-
ev.emit('chats.update', [
|
|
606
|
+
ev.emit('chats.update', [
|
|
607
|
+
{
|
|
613
608
|
id,
|
|
614
609
|
archived: isArchived,
|
|
615
610
|
conditional: getChatUpdateConditional(id, msgRange)
|
|
616
|
-
}
|
|
611
|
+
}
|
|
612
|
+
]);
|
|
617
613
|
}
|
|
618
|
-
else if (action
|
|
614
|
+
else if (action?.markChatAsReadAction) {
|
|
619
615
|
const markReadAction = action.markChatAsReadAction;
|
|
620
616
|
// basically we don't need to fire an "read" update if the chat is being marked as read
|
|
621
617
|
// because the chat is read by default
|
|
622
618
|
// this only applies for the initial sync
|
|
623
619
|
const isNullUpdate = isInitialSync && markReadAction.read;
|
|
624
|
-
ev.emit('chats.update', [
|
|
620
|
+
ev.emit('chats.update', [
|
|
621
|
+
{
|
|
625
622
|
id,
|
|
626
|
-
unreadCount: isNullUpdate ? null : !!
|
|
627
|
-
conditional: getChatUpdateConditional(id, markReadAction
|
|
628
|
-
}
|
|
623
|
+
unreadCount: isNullUpdate ? null : !!markReadAction?.read ? 0 : -1,
|
|
624
|
+
conditional: getChatUpdateConditional(id, markReadAction?.messageRange)
|
|
625
|
+
}
|
|
626
|
+
]);
|
|
629
627
|
}
|
|
630
|
-
else if (
|
|
628
|
+
else if (action?.deleteMessageForMeAction || type === 'deleteMessageForMe') {
|
|
631
629
|
ev.emit('messages.delete', {
|
|
632
630
|
keys: [
|
|
633
631
|
{
|
|
@@ -638,32 +636,41 @@ const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
|
638
636
|
]
|
|
639
637
|
});
|
|
640
638
|
}
|
|
641
|
-
else if (action
|
|
642
|
-
ev.emit('contacts.upsert', [
|
|
639
|
+
else if (action?.contactAction) {
|
|
640
|
+
ev.emit('contacts.upsert', [
|
|
641
|
+
{
|
|
642
|
+
id: id,
|
|
643
|
+
name: action.contactAction.fullName,
|
|
644
|
+
lid: action.contactAction.lidJid || undefined,
|
|
645
|
+
jid: isJidUser(id) ? id : undefined
|
|
646
|
+
}
|
|
647
|
+
]);
|
|
643
648
|
}
|
|
644
|
-
else if (action
|
|
645
|
-
const name =
|
|
646
|
-
if (name &&
|
|
649
|
+
else if (action?.pushNameSetting) {
|
|
650
|
+
const name = action?.pushNameSetting?.name;
|
|
651
|
+
if (name && me?.name !== name) {
|
|
647
652
|
ev.emit('creds.update', { me: { ...me, name } });
|
|
648
653
|
}
|
|
649
654
|
}
|
|
650
|
-
else if (action
|
|
651
|
-
ev.emit('chats.update', [
|
|
655
|
+
else if (action?.pinAction) {
|
|
656
|
+
ev.emit('chats.update', [
|
|
657
|
+
{
|
|
652
658
|
id,
|
|
653
|
-
pinned:
|
|
659
|
+
pinned: action.pinAction?.pinned ? toNumber(action.timestamp) : null,
|
|
654
660
|
conditional: getChatUpdateConditional(id, undefined)
|
|
655
|
-
}
|
|
661
|
+
}
|
|
662
|
+
]);
|
|
656
663
|
}
|
|
657
|
-
else if (action
|
|
664
|
+
else if (action?.unarchiveChatsSetting) {
|
|
658
665
|
const unarchiveChats = !!action.unarchiveChatsSetting.unarchiveChats;
|
|
659
666
|
ev.emit('creds.update', { accountSettings: { unarchiveChats } });
|
|
660
|
-
logger
|
|
667
|
+
logger?.info(`archive setting updated => '${action.unarchiveChatsSetting.unarchiveChats}'`);
|
|
661
668
|
if (accountSettings) {
|
|
662
669
|
accountSettings.unarchiveChats = unarchiveChats;
|
|
663
670
|
}
|
|
664
671
|
}
|
|
665
|
-
else if (
|
|
666
|
-
let starred =
|
|
672
|
+
else if (action?.starAction || type === 'star') {
|
|
673
|
+
let starred = action?.starAction?.starred;
|
|
667
674
|
if (typeof starred !== 'boolean') {
|
|
668
675
|
starred = syncAction.index[syncAction.index.length - 1] === '1';
|
|
669
676
|
}
|
|
@@ -674,34 +681,32 @@ const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
|
674
681
|
}
|
|
675
682
|
]);
|
|
676
683
|
}
|
|
677
|
-
else if (
|
|
684
|
+
else if (action?.deleteChatAction || type === 'deleteChat') {
|
|
678
685
|
if (!isInitialSync) {
|
|
679
686
|
ev.emit('chats.delete', [id]);
|
|
680
687
|
}
|
|
681
688
|
}
|
|
682
|
-
else if (action
|
|
689
|
+
else if (action?.labelEditAction) {
|
|
683
690
|
const { name, color, deleted, predefinedId } = action.labelEditAction;
|
|
684
691
|
ev.emit('labels.edit', {
|
|
685
|
-
id,
|
|
692
|
+
id: id,
|
|
686
693
|
name: name,
|
|
687
694
|
color: color,
|
|
688
695
|
deleted: deleted,
|
|
689
696
|
predefinedId: predefinedId ? String(predefinedId) : undefined
|
|
690
697
|
});
|
|
691
698
|
}
|
|
692
|
-
else if (action
|
|
699
|
+
else if (action?.labelAssociationAction) {
|
|
693
700
|
ev.emit('labels.association', {
|
|
694
|
-
type: action.labelAssociationAction.labeled
|
|
695
|
-
|
|
696
|
-
: 'remove',
|
|
697
|
-
association: type === LabelAssociation_1.LabelAssociationType.Chat
|
|
701
|
+
type: action.labelAssociationAction.labeled ? 'add' : 'remove',
|
|
702
|
+
association: type === LabelAssociationType.Chat
|
|
698
703
|
? {
|
|
699
|
-
type:
|
|
704
|
+
type: LabelAssociationType.Chat,
|
|
700
705
|
chatId: syncAction.index[2],
|
|
701
706
|
labelId: syncAction.index[1]
|
|
702
707
|
}
|
|
703
708
|
: {
|
|
704
|
-
type:
|
|
709
|
+
type: LabelAssociationType.Message,
|
|
705
710
|
chatId: syncAction.index[2],
|
|
706
711
|
messageId: syncAction.index[3],
|
|
707
712
|
labelId: syncAction.index[1]
|
|
@@ -709,11 +714,11 @@ const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
|
709
714
|
});
|
|
710
715
|
}
|
|
711
716
|
else {
|
|
712
|
-
logger
|
|
717
|
+
logger?.debug({ syncAction, id }, 'unprocessable update');
|
|
713
718
|
}
|
|
714
719
|
function getChatUpdateConditional(id, msgRange) {
|
|
715
720
|
return isInitialSync
|
|
716
|
-
?
|
|
721
|
+
? data => {
|
|
717
722
|
const chat = data.historySets.chats[id] || data.chatUpserts[id];
|
|
718
723
|
if (chat) {
|
|
719
724
|
return msgRange ? isValidPatchBasedOnMessageRange(chat, msgRange) : true;
|
|
@@ -722,9 +727,9 @@ const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
|
722
727
|
: undefined;
|
|
723
728
|
}
|
|
724
729
|
function isValidPatchBasedOnMessageRange(chat, msgRange) {
|
|
725
|
-
const lastMsgTimestamp = Number(
|
|
726
|
-
const chatLastMsgTimestamp = Number(
|
|
730
|
+
const lastMsgTimestamp = Number(msgRange?.lastMessageTimestamp || msgRange?.lastSystemMessageTimestamp || 0);
|
|
731
|
+
const chatLastMsgTimestamp = Number(chat?.lastMessageRecvTimestamp || 0);
|
|
727
732
|
return lastMsgTimestamp >= chatLastMsgTimestamp;
|
|
728
733
|
}
|
|
729
734
|
};
|
|
730
|
-
|
|
735
|
+
//# sourceMappingURL=chat-utils.js.map
|