@pontalabs/baileys 1.0.6 → 1.0.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/LICENSE +1 -1
- package/README.md +839 -267
- package/WAProto/GenerateStatics.sh +4 -3
- package/WAProto/WAProto.proto +511 -1215
- package/WAProto/index.d.ts +55 -14017
- package/WAProto/index.js +29 -97689
- package/lib/Defaults/index.d.ts +74 -72
- package/lib/Defaults/index.js +108 -94
- package/lib/Signal/Group/ciphertext-message.d.ts +7 -8
- package/lib/Signal/Group/ciphertext-message.js +16 -9
- package/lib/Signal/Group/group-session-builder.d.ts +13 -11
- package/lib/Signal/Group/group-session-builder.js +61 -19
- package/lib/Signal/Group/group_cipher.d.ts +16 -14
- package/lib/Signal/Group/group_cipher.js +70 -41
- package/lib/Signal/Group/index.d.ts +11 -12
- package/lib/Signal/Group/index.js +61 -12
- package/lib/Signal/Group/keyhelper.d.ts +14 -9
- package/lib/Signal/Group/keyhelper.js +58 -10
- package/lib/Signal/Group/sender-chain-key.d.ts +13 -13
- package/lib/Signal/Group/sender-chain-key.js +34 -13
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -16
- package/lib/Signal/Group/sender-key-distribution-message.js +36 -28
- package/lib/Signal/Group/sender-key-message.d.ts +18 -18
- package/lib/Signal/Group/sender-key-message.js +45 -38
- package/lib/Signal/Group/sender-key-name.d.ts +15 -14
- package/lib/Signal/Group/sender-key-name.js +31 -20
- package/lib/Signal/Group/sender-key-record.d.ts +25 -24
- package/lib/Signal/Group/sender-key-record.js +35 -18
- package/lib/Signal/Group/sender-key-state.d.ts +34 -29
- package/lib/Signal/Group/sender-key-state.js +100 -37
- package/lib/Signal/Group/sender-message-key.d.ts +10 -11
- package/lib/Signal/Group/sender-message-key.js +22 -15
- package/lib/Signal/libsignal.d.ts +8 -5
- package/lib/Signal/libsignal.js +142 -288
- package/lib/Signal/lid-mapping.d.ts +28 -23
- package/lib/Signal/lid-mapping.js +184 -277
- package/lib/Socket/Client/index.d.ts +2 -3
- package/lib/Socket/Client/index.js +22 -3
- package/lib/Socket/Client/types.d.ts +15 -15
- package/lib/Socket/Client/types.js +15 -8
- package/lib/Socket/Client/websocket.d.ts +12 -12
- package/lib/Socket/Client/websocket.js +37 -29
- package/lib/Socket/business.d.ts +178 -208
- package/lib/Socket/business.js +127 -91
- package/lib/Socket/chats.d.ts +93 -120
- package/lib/Socket/chats.js +652 -727
- package/lib/Socket/community.js +10 -2
- package/lib/Socket/groups.d.ts +111 -143
- package/lib/Socket/groups.js +186 -165
- package/lib/Socket/index.d.ts +183 -252
- package/lib/Socket/index.js +18 -38
- package/lib/Socket/messages-recv.d.ts +167 -196
- package/lib/Socket/messages-recv.js +1567 -1443
- package/lib/Socket/messages-send.d.ts +158 -192
- package/lib/Socket/messages-send.js +1208 -1102
- package/lib/Socket/newsletter.d.ts +138 -163
- package/lib/Socket/newsletter.js +249 -153
- package/lib/Socket/socket.d.ts +36 -50
- package/lib/Socket/socket.js +820 -749
- package/lib/Store/index.d.ts +4 -4
- package/lib/Store/index.js +24 -4
- package/lib/Store/make-in-memory-store.d.ts +104 -44
- package/lib/Store/make-in-memory-store.js +213 -199
- package/lib/Store/make-ordered-dictionary.d.ts +12 -13
- package/lib/Store/make-ordered-dictionary.js +45 -38
- package/lib/Store/object-repository.d.ts +10 -11
- package/lib/Store/object-repository.js +16 -9
- package/lib/Types/Auth.d.ts +97 -93
- package/lib/Types/Auth.js +3 -2
- package/lib/Types/Bussines.js +3 -2
- package/lib/Types/Call.d.ts +13 -14
- package/lib/Types/Call.js +3 -2
- package/lib/Types/Chat.d.ts +97 -78
- package/lib/Types/Chat.js +9 -8
- package/lib/Types/Contact.d.ts +9 -12
- package/lib/Types/Contact.js +3 -2
- package/lib/Types/Events.d.ts +176 -206
- package/lib/Types/Events.js +3 -2
- package/lib/Types/GroupMetadata.d.ts +48 -53
- package/lib/Types/GroupMetadata.js +3 -2
- package/lib/Types/Label.d.ts +14 -13
- package/lib/Types/Label.js +30 -24
- package/lib/Types/LabelAssociation.d.ts +20 -15
- package/lib/Types/LabelAssociation.js +12 -6
- package/lib/Types/Message.d.ts +412 -248
- package/lib/Types/Message.js +19 -17
- package/lib/Types/Product.d.ts +71 -58
- package/lib/Types/Product.js +3 -2
- package/lib/Types/Signal.d.ts +82 -71
- package/lib/Types/Signal.js +3 -2
- package/lib/Types/Socket.d.ts +81 -76
- package/lib/Types/Socket.js +3 -3
- package/lib/Types/State.d.ts +19 -75
- package/lib/Types/State.js +14 -56
- package/lib/Types/USync.d.ts +8 -8
- package/lib/Types/USync.js +3 -2
- package/lib/Types/index.d.ts +62 -47
- package/lib/Types/index.js +50 -26
- package/lib/Utils/auth-utils.d.ts +10 -13
- package/lib/Utils/auth-utils.js +472 -213
- package/lib/Utils/business.d.ts +20 -14
- package/lib/Utils/business.js +134 -110
- package/lib/Utils/chat-utils.d.ts +70 -88
- package/lib/Utils/chat-utils.js +403 -466
- package/lib/Utils/crypto.d.ts +46 -27
- package/lib/Utils/crypto.js +188 -117
- package/lib/Utils/decode-wa-message.d.ts +45 -58
- package/lib/Utils/decode-wa-message.js +311 -212
- package/lib/Utils/event-buffer.d.ts +17 -14
- package/lib/Utils/event-buffer.js +296 -321
- package/lib/Utils/generics.d.ts +92 -66
- package/lib/Utils/generics.js +436 -270
- package/lib/Utils/history.d.ts +23 -24
- package/lib/Utils/history.js +76 -106
- package/lib/Utils/index.d.ts +21 -24
- package/lib/Utils/index.js +41 -24
- package/lib/Utils/link-preview.d.ts +14 -12
- package/lib/Utils/link-preview.js +75 -40
- package/lib/Utils/logger.d.ts +11 -10
- package/lib/Utils/logger.js +7 -3
- package/lib/Utils/lt-hash.d.ts +14 -8
- package/lib/Utils/lt-hash.js +53 -3
- package/lib/Utils/make-mutex.d.ts +7 -7
- package/lib/Utils/make-mutex.js +44 -28
- package/lib/Utils/message-retry-manager.d.ts +88 -115
- package/lib/Utils/message-retry-manager.js +160 -265
- package/lib/Utils/messages-media.d.ts +107 -105
- package/lib/Utils/messages-media.js +619 -548
- package/lib/Utils/messages.d.ts +66 -52
- package/lib/Utils/messages.js +1558 -1730
- package/lib/Utils/noise-handler.d.ts +18 -18
- package/lib/Utils/noise-handler.js +130 -176
- package/lib/Utils/process-message.d.ts +32 -43
- package/lib/Utils/process-message.js +282 -484
- package/lib/Utils/rich-message-utils.js +724 -1220
- package/lib/Utils/signal.d.ts +32 -37
- package/lib/Utils/signal.js +105 -140
- package/lib/Utils/use-multi-file-auth-state.d.ts +5 -5
- package/lib/Utils/use-multi-file-auth-state.js +120 -70
- package/lib/Utils/use-single-file-auth-state.d.ts +13 -11
- package/lib/Utils/use-single-file-auth-state.js +66 -92
- package/lib/Utils/validate-connection.d.ts +13 -11
- package/lib/Utils/validate-connection.js +113 -128
- package/lib/WABinary/constants.d.ts +27 -25
- package/lib/WABinary/constants.js +1292 -1451
- package/lib/WABinary/decode.d.ts +9 -7
- package/lib/WABinary/decode.js +189 -163
- package/lib/WABinary/encode.d.ts +3 -3
- package/lib/WABinary/encode.js +155 -110
- package/lib/WABinary/generic-utils.d.ts +27 -14
- package/lib/WABinary/generic-utils.js +105 -177
- package/lib/WABinary/index.d.ts +5 -6
- package/lib/WABinary/index.js +25 -6
- package/lib/WABinary/jid-utils.d.ts +54 -41
- package/lib/WABinary/jid-utils.js +152 -83
- package/lib/WABinary/types.d.ts +13 -10
- package/lib/WABinary/types.js +3 -2
- package/lib/WAM/BinaryInfo.d.ts +15 -8
- package/lib/WAM/BinaryInfo.js +14 -7
- package/lib/WAM/constants.d.ts +37 -30
- package/lib/WAM/constants.js +11983 -19465
- package/lib/WAM/encode.d.ts +3 -3
- package/lib/WAM/encode.js +109 -95
- package/lib/WAM/index.d.ts +3 -4
- package/lib/WAM/index.js +23 -4
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -9
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +21 -37
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -19
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +26 -18
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -11
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +20 -12
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -11
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +24 -16
- package/lib/WAUSync/Protocols/index.d.ts +6 -6
- package/lib/WAUSync/Protocols/index.js +26 -6
- package/lib/WAUSync/USyncQuery.d.ts +28 -27
- package/lib/WAUSync/USyncQuery.js +62 -68
- package/lib/WAUSync/USyncUser.d.ts +10 -15
- package/lib/WAUSync/USyncUser.js +19 -20
- package/lib/WAUSync/index.d.ts +3 -4
- package/lib/WAUSync/index.js +23 -4
- package/lib/index.d.ts +12 -11
- package/lib/index.js +39 -12
- package/package.json +43 -87
- package/engine-requirements.js +0 -10
package/lib/Utils/chat-utils.js
CHANGED
|
@@ -1,136 +1,137 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true })
|
|
4
|
+
|
|
5
|
+
const boom_1 = require("@hapi/boom")
|
|
6
|
+
const WAProto_1 = require("../../WAProto")
|
|
7
|
+
const LabelAssociation_1 = require("../Types/LabelAssociation")
|
|
8
|
+
const WABinary_1 = require("../WABinary")
|
|
9
|
+
const crypto_1 = require("./crypto")
|
|
10
|
+
const generics_1 = require("./generics")
|
|
11
|
+
const lt_hash_1 = require("./lt-hash")
|
|
12
|
+
const messages_media_1 = require("./messages-media")
|
|
13
|
+
|
|
14
|
+
const mutationKeys = async (keydata) => {
|
|
15
|
+
const expanded = await crypto_1.hkdf(keydata, 160, { info: 'WhatsApp Mutation Keys' })
|
|
13
16
|
return {
|
|
14
|
-
indexKey:
|
|
15
|
-
valueEncryptionKey:
|
|
16
|
-
valueMacKey:
|
|
17
|
-
snapshotMacKey:
|
|
18
|
-
patchMacKey:
|
|
19
|
-
}
|
|
20
|
-
}
|
|
17
|
+
indexKey: expanded.slice(0, 32),
|
|
18
|
+
valueEncryptionKey: expanded.slice(32, 64),
|
|
19
|
+
valueMacKey: expanded.slice(64, 96),
|
|
20
|
+
snapshotMacKey: expanded.slice(96, 128),
|
|
21
|
+
patchMacKey: expanded.slice(128, 160)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
21
25
|
const generateMac = (operation, data, keyId, key) => {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
const getKeyData = () => {
|
|
27
|
+
let r
|
|
28
|
+
switch (operation) {
|
|
29
|
+
case WAProto_1.proto.SyncdMutation.SyncdOperation.SET:
|
|
30
|
+
r = 0x01
|
|
31
|
+
break
|
|
32
|
+
case WAProto_1.proto.SyncdMutation.SyncdOperation.REMOVE:
|
|
33
|
+
r = 0x02
|
|
34
|
+
break
|
|
35
|
+
}
|
|
36
|
+
const buff = Buffer.from([r])
|
|
37
|
+
return Buffer.concat([buff, Buffer.from(keyId, 'base64')])
|
|
38
|
+
}
|
|
39
|
+
const keyData = getKeyData()
|
|
40
|
+
const last = Buffer.alloc(8) // 8 bytes
|
|
41
|
+
last.set([keyData.length], last.length - 1)
|
|
42
|
+
const total = Buffer.concat([keyData, data, last])
|
|
43
|
+
const hmac = crypto_1.hmacSign(total, key, 'sha512')
|
|
44
|
+
return hmac.slice(0, 32)
|
|
45
|
+
}
|
|
46
|
+
|
|
36
47
|
const to64BitNetworkOrder = (e) => {
|
|
37
|
-
const buff = Buffer.alloc(8)
|
|
38
|
-
buff.writeUint32BE(e, 4)
|
|
39
|
-
return buff
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
48
|
+
const buff = Buffer.alloc(8)
|
|
49
|
+
buff.writeUint32BE(e, 4)
|
|
50
|
+
return buff
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const makeLtHashGenerator = ({ indexValueMap, hash }) => {
|
|
54
|
+
indexValueMap = { ...indexValueMap }
|
|
55
|
+
const addBuffs = []
|
|
56
|
+
const subBuffs = []
|
|
45
57
|
return {
|
|
46
58
|
mix: ({ indexMac, valueMac, operation }) => {
|
|
47
|
-
const indexMacBase64 = Buffer.from(indexMac).toString('base64')
|
|
48
|
-
const prevOp = indexValueMap[indexMacBase64]
|
|
49
|
-
if (operation === proto.SyncdMutation.SyncdOperation.REMOVE) {
|
|
59
|
+
const indexMacBase64 = Buffer.from(indexMac).toString('base64')
|
|
60
|
+
const prevOp = indexValueMap[indexMacBase64]
|
|
61
|
+
if (operation === WAProto_1.proto.SyncdMutation.SyncdOperation.REMOVE) {
|
|
50
62
|
if (!prevOp) {
|
|
51
|
-
|
|
52
|
-
// The missing REMOVE will cause an LTHash mismatch, which is handled
|
|
53
|
-
// by the MAC validation layer (snapshot recovery or retry).
|
|
54
|
-
return;
|
|
63
|
+
throw new boom_1.Boom('tried remove, but no previous op', { data: { indexMac, valueMac } })
|
|
55
64
|
}
|
|
56
65
|
// remove from index value mac, since this mutation is erased
|
|
57
|
-
delete indexValueMap[indexMacBase64]
|
|
66
|
+
delete indexValueMap[indexMacBase64]
|
|
58
67
|
}
|
|
59
68
|
else {
|
|
60
|
-
addBuffs.push(valueMac)
|
|
69
|
+
addBuffs.push(new Uint8Array(valueMac).buffer)
|
|
61
70
|
// add this index into the history map
|
|
62
|
-
indexValueMap[indexMacBase64] = { valueMac }
|
|
71
|
+
indexValueMap[indexMacBase64] = { valueMac }
|
|
63
72
|
}
|
|
64
73
|
if (prevOp) {
|
|
65
|
-
subBuffs.push(prevOp.valueMac)
|
|
74
|
+
subBuffs.push(new Uint8Array(prevOp.valueMac).buffer)
|
|
66
75
|
}
|
|
67
76
|
},
|
|
68
|
-
finish: () => {
|
|
69
|
-
const
|
|
77
|
+
finish: async () => {
|
|
78
|
+
const hashArrayBuffer = new Uint8Array(hash).buffer
|
|
79
|
+
const result = await lt_hash_1.LT_HASH_ANTI_TAMPERING.subtractThenAdd(hashArrayBuffer, addBuffs, subBuffs)
|
|
80
|
+
const buffer = Buffer.from(result)
|
|
70
81
|
return {
|
|
71
|
-
hash:
|
|
82
|
+
hash: buffer,
|
|
72
83
|
indexValueMap
|
|
73
|
-
}
|
|
84
|
+
}
|
|
74
85
|
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
77
89
|
const generateSnapshotMac = (lthash, version, name, key) => {
|
|
78
|
-
const total = Buffer.concat([
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
const total = Buffer.concat([
|
|
91
|
+
lthash,
|
|
92
|
+
to64BitNetworkOrder(version),
|
|
93
|
+
Buffer.from(name, 'utf-8')
|
|
94
|
+
])
|
|
95
|
+
return crypto_1.hmacSign(total, key, 'sha256')
|
|
96
|
+
}
|
|
97
|
+
|
|
81
98
|
const generatePatchMac = (snapshotMac, valueMacs, version, type, key) => {
|
|
82
|
-
const total = Buffer.concat([
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
* WA Web treats these as "Blocked" (waits for key arrival), not fatal.
|
|
96
|
-
* In Baileys we retry with a snapshot which may use a different key.
|
|
97
|
-
*/
|
|
98
|
-
export const isMissingKeyError = (error) => {
|
|
99
|
-
return error?.data?.isMissingKey === true;
|
|
100
|
-
};
|
|
101
|
-
/**
|
|
102
|
-
* Determines if an app state sync error is unrecoverable.
|
|
103
|
-
* TypeError indicates a WASM crash; otherwise we give up after MAX_SYNC_ATTEMPTS.
|
|
104
|
-
* Missing keys are NOT checked here — they are handled separately as "Blocked".
|
|
105
|
-
*/
|
|
106
|
-
export const isAppStateSyncIrrecoverable = (error, attempts) => {
|
|
107
|
-
return attempts >= MAX_SYNC_ATTEMPTS || error?.name === 'TypeError';
|
|
108
|
-
};
|
|
109
|
-
export const encodeSyncdPatch = async ({ type, index, syncAction, apiVersion, operation }, myAppStateKeyId, state, getAppStateSyncKey) => {
|
|
110
|
-
const key = !!myAppStateKeyId ? await getAppStateSyncKey(myAppStateKeyId) : undefined;
|
|
99
|
+
const total = Buffer.concat([
|
|
100
|
+
snapshotMac,
|
|
101
|
+
...valueMacs,
|
|
102
|
+
to64BitNetworkOrder(version),
|
|
103
|
+
Buffer.from(type, 'utf-8')
|
|
104
|
+
])
|
|
105
|
+
return crypto_1.hmacSign(total, key)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const newLTHashState = () => ({ version: 0, hash: Buffer.alloc(128), indexValueMap: {} })
|
|
109
|
+
|
|
110
|
+
const encodeSyncdPatch = async ({ type, index, syncAction, apiVersion, operation }, myAppStateKeyId, state, getAppStateSyncKey) => {
|
|
111
|
+
const key = !!myAppStateKeyId ? await getAppStateSyncKey(myAppStateKeyId) : undefined
|
|
111
112
|
if (!key) {
|
|
112
|
-
throw new Boom(`myAppStateKey ("${myAppStateKeyId}") not present`, {
|
|
113
|
+
throw new boom_1.Boom(`myAppStateKey ("${myAppStateKeyId}") not present`, { statusCode: 404 })
|
|
113
114
|
}
|
|
114
|
-
const encKeyId = Buffer.from(myAppStateKeyId, 'base64')
|
|
115
|
-
state = { ...state, indexValueMap: { ...state.indexValueMap } }
|
|
116
|
-
const indexBuffer = Buffer.from(JSON.stringify(index))
|
|
117
|
-
const dataProto = proto.SyncActionData.fromObject({
|
|
115
|
+
const encKeyId = Buffer.from(myAppStateKeyId, 'base64')
|
|
116
|
+
state = { ...state, indexValueMap: { ...state.indexValueMap } }
|
|
117
|
+
const indexBuffer = Buffer.from(JSON.stringify(index))
|
|
118
|
+
const dataProto = WAProto_1.proto.SyncActionData.fromObject({
|
|
118
119
|
index: indexBuffer,
|
|
119
120
|
value: syncAction,
|
|
120
121
|
padding: new Uint8Array(0),
|
|
121
122
|
version: apiVersion
|
|
122
|
-
})
|
|
123
|
-
const encoded = proto.SyncActionData.encode(dataProto).finish()
|
|
124
|
-
const keyValue = mutationKeys(key.keyData)
|
|
125
|
-
const encValue = aesEncrypt(encoded, keyValue.valueEncryptionKey)
|
|
126
|
-
const valueMac = generateMac(operation, encValue, encKeyId, keyValue.valueMacKey)
|
|
127
|
-
const indexMac = hmacSign(indexBuffer, keyValue.indexKey)
|
|
123
|
+
})
|
|
124
|
+
const encoded = WAProto_1.proto.SyncActionData.encode(dataProto).finish()
|
|
125
|
+
const keyValue = await mutationKeys(key.keyData)
|
|
126
|
+
const encValue = crypto_1.aesEncrypt(encoded, keyValue.valueEncryptionKey)
|
|
127
|
+
const valueMac = generateMac(operation, encValue, encKeyId, keyValue.valueMacKey)
|
|
128
|
+
const indexMac = crypto_1.hmacSign(indexBuffer, keyValue.indexKey)
|
|
128
129
|
// update LT hash
|
|
129
|
-
const generator = makeLtHashGenerator(state)
|
|
130
|
-
generator.mix({ indexMac, valueMac, operation })
|
|
131
|
-
Object.assign(state, generator.finish())
|
|
132
|
-
state.version += 1
|
|
133
|
-
const snapshotMac = generateSnapshotMac(state.hash, state.version, type, keyValue.snapshotMacKey)
|
|
130
|
+
const generator = makeLtHashGenerator(state)
|
|
131
|
+
generator.mix({ indexMac, valueMac, operation })
|
|
132
|
+
Object.assign(state, await generator.finish())
|
|
133
|
+
state.version += 1
|
|
134
|
+
const snapshotMac = generateSnapshotMac(state.hash, state.version, type, keyValue.snapshotMacKey)
|
|
134
135
|
const patch = {
|
|
135
136
|
patchMac: generatePatchMac(snapshotMac, [valueMac], state.version, type, keyValue.patchMacKey),
|
|
136
137
|
snapshotMac: snapshotMac,
|
|
@@ -149,271 +150,236 @@ export const encodeSyncdPatch = async ({ type, index, syncAction, apiVersion, op
|
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
]
|
|
152
|
-
}
|
|
153
|
-
const base64Index = indexMac.toString('base64')
|
|
154
|
-
state.indexValueMap[base64Index] = { valueMac }
|
|
155
|
-
return { patch, state }
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const
|
|
153
|
+
}
|
|
154
|
+
const base64Index = indexMac.toString('base64')
|
|
155
|
+
state.indexValueMap[base64Index] = { valueMac }
|
|
156
|
+
return { patch, state }
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncKey, onMutation, validateMacs) => {
|
|
160
|
+
const ltGenerator = makeLtHashGenerator(initialState)
|
|
160
161
|
// indexKey used to HMAC sign record.index.blob
|
|
161
162
|
// valueEncryptionKey used to AES-256-CBC encrypt record.value.blob[0:-32]
|
|
162
163
|
// 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
|
|
163
164
|
for (const msgMutation of msgMutations) {
|
|
164
165
|
// if it's a syncdmutation, get the operation property
|
|
165
166
|
// otherwise, if it's only a record -- it'll be a SET mutation
|
|
166
|
-
const operation = 'operation' in msgMutation ? msgMutation.operation : proto.SyncdMutation.SyncdOperation.SET
|
|
167
|
-
const record = 'record' in msgMutation && !!msgMutation.record ? msgMutation.record : msgMutation
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
catch (err) {
|
|
173
|
-
// Missing-key errors must propagate so the orchestrator can park the
|
|
174
|
-
// collection (Blocked) and retry when APP_STATE_SYNC_KEY_SHARE arrives.
|
|
175
|
-
// Other errors → individual record corruption, skip and keep going.
|
|
176
|
-
if (isMissingKeyError(err))
|
|
177
|
-
throw err;
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
const content = record.value.blob;
|
|
181
|
-
const encContent = content.subarray(0, -32);
|
|
182
|
-
const ogValueMac = content.subarray(-32);
|
|
167
|
+
const operation = 'operation' in msgMutation ? msgMutation.operation : WAProto_1.proto.SyncdMutation.SyncdOperation.SET
|
|
168
|
+
const record = ('record' in msgMutation && !!msgMutation.record) ? msgMutation.record : msgMutation
|
|
169
|
+
const key = await getKey(record.keyId.id)
|
|
170
|
+
const content = Buffer.from(record.value.blob)
|
|
171
|
+
const encContent = content.slice(0, -32)
|
|
172
|
+
const ogValueMac = content.slice(-32)
|
|
183
173
|
if (validateMacs) {
|
|
184
|
-
const contentHmac = generateMac(operation, encContent, record.keyId.id, key.valueMacKey)
|
|
174
|
+
const contentHmac = generateMac(operation, encContent, record.keyId.id, key.valueMacKey)
|
|
185
175
|
if (Buffer.compare(contentHmac, ogValueMac) !== 0) {
|
|
186
|
-
|
|
187
|
-
continue;
|
|
176
|
+
throw new boom_1.Boom('HMAC content verification failed')
|
|
188
177
|
}
|
|
189
178
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
result = aesDecrypt(encContent, key.valueEncryptionKey);
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
// decrypt failed — skip this record instead of aborting
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
const syncAction = proto.SyncActionData.decode(result);
|
|
179
|
+
const result = crypto_1.aesDecrypt(encContent, key.valueEncryptionKey)
|
|
180
|
+
const syncAction = WAProto_1.proto.SyncActionData.decode(result)
|
|
199
181
|
if (validateMacs) {
|
|
200
|
-
const hmac = hmacSign(syncAction.index, key.indexKey)
|
|
182
|
+
const hmac = crypto_1.hmacSign(syncAction.index, key.indexKey)
|
|
201
183
|
if (Buffer.compare(hmac, record.index.blob) !== 0) {
|
|
202
|
-
throw new Boom('HMAC index verification failed')
|
|
184
|
+
throw new boom_1.Boom('HMAC index verification failed')
|
|
203
185
|
}
|
|
204
186
|
}
|
|
205
|
-
const indexStr = Buffer.from(syncAction.index).toString()
|
|
206
|
-
onMutation({ syncAction, index: JSON.parse(indexStr) })
|
|
187
|
+
const indexStr = Buffer.from(syncAction.index).toString()
|
|
188
|
+
onMutation({ syncAction, index: JSON.parse(indexStr) })
|
|
207
189
|
ltGenerator.mix({
|
|
208
190
|
indexMac: record.index.blob,
|
|
209
191
|
valueMac: ogValueMac,
|
|
210
192
|
operation: operation
|
|
211
|
-
})
|
|
193
|
+
})
|
|
212
194
|
}
|
|
213
|
-
return ltGenerator.finish()
|
|
195
|
+
return await ltGenerator.finish()
|
|
214
196
|
async function getKey(keyId) {
|
|
215
|
-
const base64Key = Buffer.from(keyId).toString('base64')
|
|
216
|
-
const
|
|
217
|
-
if (cached) {
|
|
218
|
-
return cached;
|
|
219
|
-
}
|
|
220
|
-
const keyEnc = await getAppStateSyncKey(base64Key);
|
|
197
|
+
const base64Key = Buffer.from(keyId).toString('base64')
|
|
198
|
+
const keyEnc = await getAppStateSyncKey(base64Key)
|
|
221
199
|
if (!keyEnc) {
|
|
222
|
-
throw new Boom(`failed to find key "${base64Key}" to decode mutation`, {
|
|
223
|
-
data: { isMissingKey: true, msgMutations }
|
|
224
|
-
});
|
|
200
|
+
throw new boom_1.Boom(`failed to find key "${base64Key}" to decode mutation`, { statusCode: 404, data: { msgMutations } })
|
|
225
201
|
}
|
|
226
|
-
|
|
227
|
-
derivedKeyCache.set(base64Key, keys);
|
|
228
|
-
return keys;
|
|
202
|
+
return mutationKeys(keyEnc.keyData)
|
|
229
203
|
}
|
|
230
|
-
}
|
|
231
|
-
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const decodeSyncdPatch = async (msg, name, initialState, getAppStateSyncKey, onMutation, validateMacs) => {
|
|
232
207
|
if (validateMacs) {
|
|
233
|
-
const base64Key = Buffer.from(msg.keyId.id).toString('base64')
|
|
234
|
-
const mainKeyObj = await getAppStateSyncKey(base64Key)
|
|
208
|
+
const base64Key = Buffer.from(msg.keyId.id).toString('base64')
|
|
209
|
+
const mainKeyObj = await getAppStateSyncKey(base64Key)
|
|
235
210
|
if (!mainKeyObj) {
|
|
236
|
-
throw new Boom(`failed to find key "${base64Key}" to decode patch`, {
|
|
211
|
+
throw new boom_1.Boom(`failed to find key "${base64Key}" to decode patch`, { statusCode: 404, data: { msg } })
|
|
237
212
|
}
|
|
238
|
-
const mainKey = mutationKeys(mainKeyObj.keyData)
|
|
239
|
-
const mutationmacs = msg.mutations.map(mutation => mutation.record.value.blob.slice(-32))
|
|
240
|
-
const patchMac = generatePatchMac(msg.snapshotMac, mutationmacs, toNumber(msg.version.version), name, mainKey.patchMacKey)
|
|
213
|
+
const mainKey = await mutationKeys(mainKeyObj.keyData)
|
|
214
|
+
const mutationmacs = msg.mutations.map(mutation => mutation.record.value.blob.slice(-32))
|
|
215
|
+
const patchMac = generatePatchMac(msg.snapshotMac, mutationmacs, generics_1.toNumber(msg.version.version), name, mainKey.patchMacKey)
|
|
241
216
|
if (Buffer.compare(patchMac, msg.patchMac) !== 0) {
|
|
242
|
-
throw new Boom('Invalid patch mac')
|
|
217
|
+
throw new boom_1.Boom('Invalid patch mac')
|
|
243
218
|
}
|
|
244
219
|
}
|
|
245
|
-
const result = await decodeSyncdMutations(msg.mutations, initialState, getAppStateSyncKey, onMutation, validateMacs)
|
|
246
|
-
return result
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const
|
|
251
|
-
const
|
|
220
|
+
const result = await decodeSyncdMutations(msg.mutations, initialState, getAppStateSyncKey, onMutation, validateMacs)
|
|
221
|
+
return result
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const extractSyncdPatches = async (result, options) => {
|
|
225
|
+
const syncNode = WABinary_1.getBinaryNodeChild(result, 'sync')
|
|
226
|
+
const collectionNodes = WABinary_1.getBinaryNodeChildren(syncNode, 'collection')
|
|
227
|
+
const final = {}
|
|
252
228
|
await Promise.all(collectionNodes.map(async (collectionNode) => {
|
|
253
|
-
const patchesNode = getBinaryNodeChild(collectionNode, 'patches')
|
|
254
|
-
const patches = getBinaryNodeChildren(patchesNode || collectionNode, 'patch')
|
|
255
|
-
const snapshotNode = getBinaryNodeChild(collectionNode, 'snapshot')
|
|
256
|
-
const syncds = []
|
|
257
|
-
const name = collectionNode.attrs.name
|
|
258
|
-
const hasMorePatches = collectionNode.attrs.has_more_patches === 'true'
|
|
259
|
-
let snapshot = undefined
|
|
229
|
+
const patchesNode = WABinary_1.getBinaryNodeChild(collectionNode, 'patches')
|
|
230
|
+
const patches = WABinary_1.getBinaryNodeChildren(patchesNode || collectionNode, 'patch')
|
|
231
|
+
const snapshotNode = WABinary_1.getBinaryNodeChild(collectionNode, 'snapshot')
|
|
232
|
+
const syncds = []
|
|
233
|
+
const name = collectionNode.attrs.name
|
|
234
|
+
const hasMorePatches = collectionNode.attrs.has_more_patches === 'true'
|
|
235
|
+
let snapshot = undefined
|
|
260
236
|
if (snapshotNode && !!snapshotNode.content) {
|
|
261
237
|
if (!Buffer.isBuffer(snapshotNode)) {
|
|
262
|
-
snapshotNode.content = Buffer.from(Object.values(snapshotNode.content))
|
|
238
|
+
snapshotNode.content = Buffer.from(Object.values(snapshotNode.content))
|
|
263
239
|
}
|
|
264
|
-
const blobRef = proto.ExternalBlobReference.decode(snapshotNode.content)
|
|
265
|
-
const data = await downloadExternalBlob(blobRef, options)
|
|
266
|
-
snapshot = proto.SyncdSnapshot.decode(data)
|
|
240
|
+
const blobRef = WAProto_1.proto.ExternalBlobReference.decode(snapshotNode.content)
|
|
241
|
+
const data = await downloadExternalBlob(blobRef, options)
|
|
242
|
+
snapshot = WAProto_1.proto.SyncdSnapshot.decode(data)
|
|
267
243
|
}
|
|
268
244
|
for (let { content } of patches) {
|
|
269
245
|
if (content) {
|
|
270
246
|
if (!Buffer.isBuffer(content)) {
|
|
271
|
-
content = Buffer.from(Object.values(content))
|
|
247
|
+
content = Buffer.from(Object.values(content))
|
|
272
248
|
}
|
|
273
|
-
const syncd = proto.SyncdPatch.decode(content)
|
|
249
|
+
const syncd = WAProto_1.proto.SyncdPatch.decode(content)
|
|
274
250
|
if (!syncd.version) {
|
|
275
|
-
syncd.version = { version: +collectionNode.attrs.version + 1 }
|
|
251
|
+
syncd.version = { version: +collectionNode.attrs.version + 1 }
|
|
276
252
|
}
|
|
277
|
-
syncds.push(syncd)
|
|
253
|
+
syncds.push(syncd)
|
|
278
254
|
}
|
|
279
255
|
}
|
|
280
|
-
final[name] = { patches: syncds, hasMorePatches, snapshot }
|
|
281
|
-
}))
|
|
282
|
-
return final
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const
|
|
256
|
+
final[name] = { patches: syncds, hasMorePatches, snapshot }
|
|
257
|
+
}))
|
|
258
|
+
return final
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const downloadExternalBlob = async (blob, options) => {
|
|
262
|
+
const stream = await messages_media_1.downloadContentFromMessage(blob, 'md-app-state', { options })
|
|
263
|
+
const bufferArray = []
|
|
287
264
|
for await (const chunk of stream) {
|
|
288
|
-
bufferArray.push(chunk)
|
|
289
|
-
}
|
|
290
|
-
return Buffer.concat(bufferArray)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const
|
|
301
|
-
|
|
265
|
+
bufferArray.push(chunk)
|
|
266
|
+
}
|
|
267
|
+
return Buffer.concat(bufferArray)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const downloadExternalPatch = async (blob, options) => {
|
|
271
|
+
const buffer = await downloadExternalBlob(blob, options)
|
|
272
|
+
const syncData = WAProto_1.proto.SyncdMutations.decode(buffer)
|
|
273
|
+
return syncData
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const decodeSyncdSnapshot = async (name, snapshot, getAppStateSyncKey, minimumVersionNumber, validateMacs = true) => {
|
|
277
|
+
const newState = newLTHashState()
|
|
278
|
+
newState.version = generics_1.toNumber(snapshot.version.version)
|
|
279
|
+
const mutationMap = {}
|
|
280
|
+
const areMutationsRequired = typeof minimumVersionNumber === 'undefined'
|
|
281
|
+
|| newState.version > minimumVersionNumber
|
|
302
282
|
const { hash, indexValueMap } = await decodeSyncdMutations(snapshot.records, newState, getAppStateSyncKey, areMutationsRequired
|
|
303
|
-
? mutation => {
|
|
304
|
-
const index = mutation.syncAction.index?.toString()
|
|
305
|
-
mutationMap[index] = mutation
|
|
283
|
+
? (mutation) => {
|
|
284
|
+
const index = mutation.syncAction.index?.toString()
|
|
285
|
+
mutationMap[index] = mutation
|
|
306
286
|
}
|
|
307
|
-
: () => { }, validateMacs)
|
|
308
|
-
newState.hash = hash
|
|
309
|
-
newState.indexValueMap = indexValueMap
|
|
287
|
+
: () => { }, validateMacs)
|
|
288
|
+
newState.hash = hash
|
|
289
|
+
newState.indexValueMap = indexValueMap
|
|
310
290
|
if (validateMacs) {
|
|
311
|
-
const base64Key = Buffer.from(snapshot.keyId.id).toString('base64')
|
|
312
|
-
const keyEnc = await getAppStateSyncKey(base64Key)
|
|
291
|
+
const base64Key = Buffer.from(snapshot.keyId.id).toString('base64')
|
|
292
|
+
const keyEnc = await getAppStateSyncKey(base64Key)
|
|
313
293
|
if (!keyEnc) {
|
|
314
|
-
throw new Boom(`failed to find key "${base64Key}" to decode mutation
|
|
294
|
+
throw new boom_1.Boom(`failed to find key "${base64Key}" to decode mutation`)
|
|
315
295
|
}
|
|
316
|
-
const result = mutationKeys(keyEnc.keyData)
|
|
317
|
-
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
|
296
|
+
const result = await mutationKeys(keyEnc.keyData)
|
|
297
|
+
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
|
318
298
|
if (Buffer.compare(snapshot.mac, computedSnapshotMac) !== 0) {
|
|
319
|
-
|
|
320
|
-
// records (poisoned server-side snapshot); the aggregate client hash diverges
|
|
321
|
-
// from the server-computed mac. Fall through with a warning so the session stays
|
|
322
|
-
// alive with partial state, symmetric to how decodePatches handles its own
|
|
323
|
-
// LTHash mismatch a few lines below.
|
|
324
|
-
logger?.warn({ name, version: newState.version }, 'LTHash verification failed on snapshot, continuing with partial state');
|
|
299
|
+
throw new boom_1.Boom(`failed to verify LTHash at ${newState.version} of ${name} from snapshot`)
|
|
325
300
|
}
|
|
326
301
|
}
|
|
327
302
|
return {
|
|
328
303
|
state: newState,
|
|
329
304
|
mutationMap
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const decodePatches = async (name, syncds, initial, getAppStateSyncKey, options, minimumVersionNumber, logger, validateMacs = true) => {
|
|
333
309
|
const newState = {
|
|
334
310
|
...initial,
|
|
335
311
|
indexValueMap: { ...initial.indexValueMap }
|
|
336
|
-
}
|
|
337
|
-
const mutationMap = {}
|
|
312
|
+
}
|
|
313
|
+
const mutationMap = {}
|
|
338
314
|
for (const syncd of syncds) {
|
|
339
|
-
const { version, keyId, snapshotMac } = syncd
|
|
315
|
+
const { version, keyId, snapshotMac } = syncd
|
|
340
316
|
if (syncd.externalMutations) {
|
|
341
|
-
logger?.trace({ name, version }, 'downloading external patch')
|
|
342
|
-
const ref = await downloadExternalPatch(syncd.externalMutations, options)
|
|
343
|
-
logger?.debug({ name, version, mutations: ref.mutations.length }, 'downloaded external patch')
|
|
344
|
-
syncd.mutations?.push(...ref.mutations)
|
|
345
|
-
}
|
|
346
|
-
const patchVersion = toNumber(version.version);
|
|
347
|
-
newState.version = patchVersion;
|
|
348
|
-
const shouldMutate = typeof minimumVersionNumber === 'undefined' || patchVersion > minimumVersionNumber;
|
|
349
|
-
let decodeResult;
|
|
350
|
-
try {
|
|
351
|
-
decodeResult = await decodeSyncdPatch(syncd, name, newState, getAppStateSyncKey, shouldMutate
|
|
352
|
-
? mutation => {
|
|
353
|
-
const index = mutation.syncAction.index?.toString();
|
|
354
|
-
mutationMap[index] = mutation;
|
|
355
|
-
}
|
|
356
|
-
: () => { }, validateMacs);
|
|
317
|
+
logger?.trace({ name, version }, 'downloading external patch')
|
|
318
|
+
const ref = await downloadExternalPatch(syncd.externalMutations, options)
|
|
319
|
+
logger?.debug({ name, version, mutations: ref.mutations.length }, 'downloaded external patch')
|
|
320
|
+
syncd.mutations?.push(...ref.mutations)
|
|
357
321
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
322
|
+
const patchVersion = generics_1.toNumber(version.version)
|
|
323
|
+
newState.version = patchVersion
|
|
324
|
+
const shouldMutate = typeof minimumVersionNumber === 'undefined' || patchVersion > minimumVersionNumber
|
|
325
|
+
const decodeResult = await decodeSyncdPatch(syncd, name, newState, getAppStateSyncKey, shouldMutate
|
|
326
|
+
? mutation => {
|
|
327
|
+
var _a
|
|
328
|
+
const index = mutation.syncAction.index?.toString()
|
|
329
|
+
mutationMap[index] = mutation
|
|
330
|
+
}
|
|
331
|
+
: (() => { }), true)
|
|
332
|
+
newState.hash = decodeResult.hash
|
|
333
|
+
newState.indexValueMap = decodeResult.indexValueMap
|
|
366
334
|
if (validateMacs) {
|
|
367
|
-
const base64Key = Buffer.from(keyId.id).toString('base64')
|
|
368
|
-
const keyEnc = await getAppStateSyncKey(base64Key)
|
|
335
|
+
const base64Key = Buffer.from(keyId.id).toString('base64')
|
|
336
|
+
const keyEnc = await getAppStateSyncKey(base64Key)
|
|
369
337
|
if (!keyEnc) {
|
|
370
|
-
throw new Boom(`failed to find key "${base64Key}" to decode mutation
|
|
338
|
+
throw new boom_1.Boom(`failed to find key "${base64Key}" to decode mutation`)
|
|
371
339
|
}
|
|
372
|
-
const result = mutationKeys(keyEnc.keyData)
|
|
373
|
-
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
|
340
|
+
const result = await mutationKeys(keyEnc.keyData)
|
|
341
|
+
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
|
374
342
|
if (Buffer.compare(snapshotMac, computedSnapshotMac) !== 0) {
|
|
375
|
-
|
|
376
|
-
break;
|
|
343
|
+
throw new boom_1.Boom(`failed to verify LTHash at ${newState.version} of ${name}`)
|
|
377
344
|
}
|
|
378
345
|
}
|
|
379
346
|
// clear memory used up by the mutations
|
|
380
|
-
syncd.mutations = []
|
|
347
|
+
syncd.mutations = []
|
|
381
348
|
}
|
|
382
|
-
return { state: newState, mutationMap }
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
|
|
349
|
+
return { state: newState, mutationMap }
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const chatModificationToAppPatch = (mod, jid) => {
|
|
353
|
+
const OP = WAProto_1.proto.SyncdMutation.SyncdOperation
|
|
386
354
|
const getMessageRange = (lastMessages) => {
|
|
387
|
-
let messageRange
|
|
355
|
+
let messageRange
|
|
388
356
|
if (Array.isArray(lastMessages)) {
|
|
389
|
-
const lastMsg = lastMessages[lastMessages.length - 1]
|
|
357
|
+
const lastMsg = lastMessages[lastMessages.length - 1]
|
|
390
358
|
messageRange = {
|
|
391
359
|
lastMessageTimestamp: lastMsg?.messageTimestamp,
|
|
392
|
-
messages: lastMessages?.length
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
: undefined
|
|
409
|
-
};
|
|
360
|
+
messages: lastMessages?.length ? lastMessages.map(m => {
|
|
361
|
+
if (!((m.key?.id) || (m.key?.remoteJid))) {
|
|
362
|
+
throw new boom_1.Boom('Incomplete key', { statusCode: 400, data: m })
|
|
363
|
+
}
|
|
364
|
+
if (WABinary_1.isJidGroup(m.key.remoteJid) && !m.key.fromMe && !m.key.participant) {
|
|
365
|
+
throw new boom_1.Boom('Expected not from me message to have participant', { statusCode: 400, data: m })
|
|
366
|
+
}
|
|
367
|
+
if (!m.messageTimestamp || !generics_1.toNumber(m.messageTimestamp)) {
|
|
368
|
+
throw new boom_1.Boom('Missing timestamp in last message list', { statusCode: 400, data: m })
|
|
369
|
+
}
|
|
370
|
+
if (m.key.participant) {
|
|
371
|
+
m.key.participant = WABinary_1.jidNormalizedUser(m.key.participant)
|
|
372
|
+
}
|
|
373
|
+
return m
|
|
374
|
+
}) : undefined
|
|
375
|
+
}
|
|
410
376
|
}
|
|
411
377
|
else {
|
|
412
|
-
messageRange = lastMessages
|
|
378
|
+
messageRange = lastMessages
|
|
413
379
|
}
|
|
414
|
-
return messageRange
|
|
415
|
-
}
|
|
416
|
-
let patch
|
|
380
|
+
return messageRange
|
|
381
|
+
}
|
|
382
|
+
let patch
|
|
417
383
|
if ('mute' in mod) {
|
|
418
384
|
patch = {
|
|
419
385
|
syncAction: {
|
|
@@ -426,7 +392,7 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
426
392
|
type: 'regular_high',
|
|
427
393
|
apiVersion: 2,
|
|
428
394
|
operation: OP.SET
|
|
429
|
-
}
|
|
395
|
+
}
|
|
430
396
|
}
|
|
431
397
|
else if ('archive' in mod) {
|
|
432
398
|
patch = {
|
|
@@ -440,7 +406,7 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
440
406
|
type: 'regular_low',
|
|
441
407
|
apiVersion: 3,
|
|
442
408
|
operation: OP.SET
|
|
443
|
-
}
|
|
409
|
+
}
|
|
444
410
|
}
|
|
445
411
|
else if ('markRead' in mod) {
|
|
446
412
|
patch = {
|
|
@@ -454,10 +420,10 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
454
420
|
type: 'regular_low',
|
|
455
421
|
apiVersion: 3,
|
|
456
422
|
operation: OP.SET
|
|
457
|
-
}
|
|
423
|
+
}
|
|
458
424
|
}
|
|
459
425
|
else if ('deleteForMe' in mod) {
|
|
460
|
-
const { timestamp, key, deleteMedia } = mod.deleteForMe
|
|
426
|
+
const { timestamp, key, deleteMedia } = mod.deleteForMe
|
|
461
427
|
patch = {
|
|
462
428
|
syncAction: {
|
|
463
429
|
deleteMessageForMeAction: {
|
|
@@ -469,20 +435,20 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
469
435
|
type: 'regular_high',
|
|
470
436
|
apiVersion: 3,
|
|
471
437
|
operation: OP.SET
|
|
472
|
-
}
|
|
438
|
+
}
|
|
473
439
|
}
|
|
474
440
|
else if ('clear' in mod) {
|
|
475
441
|
patch = {
|
|
476
442
|
syncAction: {
|
|
477
443
|
clearChatAction: {
|
|
478
|
-
messageRange: getMessageRange(mod.lastMessages)
|
|
444
|
+
messageRange: getMessageRange(mod.lastMessages)
|
|
479
445
|
}
|
|
480
446
|
},
|
|
481
447
|
index: ['clearChat', jid, '1' /*the option here is 0 when keep starred messages is enabled*/, '0'],
|
|
482
448
|
type: 'regular_high',
|
|
483
449
|
apiVersion: 6,
|
|
484
450
|
operation: OP.SET
|
|
485
|
-
}
|
|
451
|
+
}
|
|
486
452
|
}
|
|
487
453
|
else if ('pin' in mod) {
|
|
488
454
|
patch = {
|
|
@@ -495,32 +461,32 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
495
461
|
type: 'regular_low',
|
|
496
462
|
apiVersion: 5,
|
|
497
463
|
operation: OP.SET
|
|
498
|
-
}
|
|
464
|
+
}
|
|
499
465
|
}
|
|
500
466
|
else if ('contact' in mod) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
},
|
|
505
|
-
index: ['contact', jid],
|
|
506
|
-
type: 'critical_unblock_low',
|
|
467
|
+
patch = {
|
|
468
|
+
syncAction: {
|
|
469
|
+
contactAction: mod?.contact || {}
|
|
470
|
+
},
|
|
471
|
+
index: ['contact', jid],
|
|
472
|
+
type: 'critical_unblock_low',
|
|
507
473
|
apiVersion: 2,
|
|
508
474
|
operation: mod.contact ? OP.SET : OP.REMOVE
|
|
509
|
-
}
|
|
475
|
+
}
|
|
510
476
|
}
|
|
511
477
|
else if ('disableLinkPreviews' in mod) {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
478
|
+
patch = {
|
|
479
|
+
syncAction: {
|
|
480
|
+
privacySettingDisableLinkPreviewsAction: mod.disableLinkPreviews || {}
|
|
481
|
+
},
|
|
482
|
+
index: ['setting_disableLinkPreviews'],
|
|
483
|
+
type: 'regular',
|
|
484
|
+
apiVersion: 8,
|
|
485
|
+
operation: OP.SET
|
|
486
|
+
}
|
|
521
487
|
}
|
|
522
488
|
else if ('star' in mod) {
|
|
523
|
-
const key = mod.star.messages[0]
|
|
489
|
+
const key = mod.star.messages[0]
|
|
524
490
|
patch = {
|
|
525
491
|
syncAction: {
|
|
526
492
|
starAction: {
|
|
@@ -531,20 +497,20 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
531
497
|
type: 'regular_low',
|
|
532
498
|
apiVersion: 2,
|
|
533
499
|
operation: OP.SET
|
|
534
|
-
}
|
|
500
|
+
}
|
|
535
501
|
}
|
|
536
502
|
else if ('delete' in mod) {
|
|
537
503
|
patch = {
|
|
538
504
|
syncAction: {
|
|
539
505
|
deleteChatAction: {
|
|
540
|
-
messageRange: getMessageRange(mod.lastMessages)
|
|
506
|
+
messageRange: getMessageRange(mod.lastMessages),
|
|
541
507
|
}
|
|
542
508
|
},
|
|
543
509
|
index: ['deleteChat', jid, '1'],
|
|
544
510
|
type: 'regular_high',
|
|
545
511
|
apiVersion: 6,
|
|
546
512
|
operation: OP.SET
|
|
547
|
-
}
|
|
513
|
+
}
|
|
548
514
|
}
|
|
549
515
|
else if ('pushNameSetting' in mod) {
|
|
550
516
|
patch = {
|
|
@@ -556,8 +522,8 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
556
522
|
index: ['setting_pushName'],
|
|
557
523
|
type: 'critical_block',
|
|
558
524
|
apiVersion: 1,
|
|
559
|
-
operation: OP.SET
|
|
560
|
-
}
|
|
525
|
+
operation: OP.SET,
|
|
526
|
+
}
|
|
561
527
|
}
|
|
562
528
|
else if ('quickReply' in mod) {
|
|
563
529
|
patch = {
|
|
@@ -574,7 +540,7 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
574
540
|
type: 'regular',
|
|
575
541
|
apiVersion: 2,
|
|
576
542
|
operation: OP.SET
|
|
577
|
-
}
|
|
543
|
+
}
|
|
578
544
|
}
|
|
579
545
|
else if ('addLabel' in mod) {
|
|
580
546
|
patch = {
|
|
@@ -589,57 +555,64 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
589
555
|
index: ['label_edit', mod.addLabel.id],
|
|
590
556
|
type: 'regular',
|
|
591
557
|
apiVersion: 3,
|
|
592
|
-
operation: OP.SET
|
|
593
|
-
}
|
|
558
|
+
operation: OP.SET,
|
|
559
|
+
}
|
|
594
560
|
}
|
|
595
561
|
else if ('addChatLabel' in mod) {
|
|
596
562
|
patch = {
|
|
597
563
|
syncAction: {
|
|
598
564
|
labelAssociationAction: {
|
|
599
|
-
labeled: true
|
|
565
|
+
labeled: true,
|
|
600
566
|
}
|
|
601
567
|
},
|
|
602
|
-
index: [LabelAssociationType.Chat, mod.addChatLabel.labelId, jid],
|
|
568
|
+
index: [LabelAssociation_1.LabelAssociationType.Chat, mod.addChatLabel.labelId, jid],
|
|
603
569
|
type: 'regular',
|
|
604
570
|
apiVersion: 3,
|
|
605
|
-
operation: OP.SET
|
|
606
|
-
}
|
|
571
|
+
operation: OP.SET,
|
|
572
|
+
}
|
|
607
573
|
}
|
|
608
574
|
else if ('removeChatLabel' in mod) {
|
|
609
575
|
patch = {
|
|
610
576
|
syncAction: {
|
|
611
577
|
labelAssociationAction: {
|
|
612
|
-
labeled: false
|
|
578
|
+
labeled: false,
|
|
613
579
|
}
|
|
614
580
|
},
|
|
615
|
-
index: [LabelAssociationType.Chat, mod.removeChatLabel.labelId, jid],
|
|
581
|
+
index: [LabelAssociation_1.LabelAssociationType.Chat, mod.removeChatLabel.labelId, jid],
|
|
616
582
|
type: 'regular',
|
|
617
583
|
apiVersion: 3,
|
|
618
|
-
operation: OP.SET
|
|
619
|
-
}
|
|
584
|
+
operation: OP.SET,
|
|
585
|
+
}
|
|
620
586
|
}
|
|
621
587
|
else if ('addMessageLabel' in mod) {
|
|
622
588
|
patch = {
|
|
623
589
|
syncAction: {
|
|
624
590
|
labelAssociationAction: {
|
|
625
|
-
labeled: true
|
|
591
|
+
labeled: true,
|
|
626
592
|
}
|
|
627
593
|
},
|
|
628
|
-
index: [
|
|
594
|
+
index: [
|
|
595
|
+
LabelAssociation_1.LabelAssociationType.Message,
|
|
596
|
+
mod.addMessageLabel.labelId,
|
|
597
|
+
jid,
|
|
598
|
+
mod.addMessageLabel.messageId,
|
|
599
|
+
'0',
|
|
600
|
+
'0'
|
|
601
|
+
],
|
|
629
602
|
type: 'regular',
|
|
630
603
|
apiVersion: 3,
|
|
631
|
-
operation: OP.SET
|
|
632
|
-
}
|
|
604
|
+
operation: OP.SET,
|
|
605
|
+
}
|
|
633
606
|
}
|
|
634
607
|
else if ('removeMessageLabel' in mod) {
|
|
635
608
|
patch = {
|
|
636
609
|
syncAction: {
|
|
637
610
|
labelAssociationAction: {
|
|
638
|
-
labeled: false
|
|
611
|
+
labeled: false,
|
|
639
612
|
}
|
|
640
613
|
},
|
|
641
614
|
index: [
|
|
642
|
-
LabelAssociationType.Message,
|
|
615
|
+
LabelAssociation_1.LabelAssociationType.Message,
|
|
643
616
|
mod.removeMessageLabel.labelId,
|
|
644
617
|
jid,
|
|
645
618
|
mod.removeMessageLabel.messageId,
|
|
@@ -648,28 +621,31 @@ export const chatModificationToAppPatch = (mod, jid) => {
|
|
|
648
621
|
],
|
|
649
622
|
type: 'regular',
|
|
650
623
|
apiVersion: 3,
|
|
651
|
-
operation: OP.SET
|
|
652
|
-
}
|
|
624
|
+
operation: OP.SET,
|
|
625
|
+
}
|
|
653
626
|
}
|
|
654
627
|
else {
|
|
655
|
-
throw new Boom('not supported')
|
|
656
|
-
}
|
|
657
|
-
patch.syncAction.timestamp = Date.now()
|
|
658
|
-
return patch
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
const
|
|
663
|
-
|
|
664
|
-
|
|
628
|
+
throw new boom_1.Boom('not supported')
|
|
629
|
+
}
|
|
630
|
+
patch.syncAction.timestamp = Date.now()
|
|
631
|
+
return patch
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
635
|
+
const isInitialSync = !!initialSyncOpts
|
|
636
|
+
const accountSettings = initialSyncOpts?.accountSettings
|
|
637
|
+
logger?.trace({ syncAction, initialSync: !!initialSyncOpts }, 'processing sync action')
|
|
638
|
+
const { syncAction: { value: action }, index: [type, id, msgId, fromMe] } = syncAction
|
|
665
639
|
if (action?.muteAction) {
|
|
666
640
|
ev.emit('chats.update', [
|
|
667
641
|
{
|
|
668
642
|
id,
|
|
669
|
-
muteEndTime: action.muteAction?.muted
|
|
643
|
+
muteEndTime: action.muteAction?.muted
|
|
644
|
+
? generics_1.toNumber(action.muteAction.muteEndTimestamp)
|
|
645
|
+
: null,
|
|
670
646
|
conditional: getChatUpdateConditional(id, undefined)
|
|
671
647
|
}
|
|
672
|
-
])
|
|
648
|
+
])
|
|
673
649
|
}
|
|
674
650
|
else if (action?.archiveChatAction || type === 'archive' || type === 'unarchive') {
|
|
675
651
|
// okay so we've to do some annoying computation here
|
|
@@ -678,40 +654,38 @@ export const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) =
|
|
|
678
654
|
// 1. if the account unarchiveChats setting is true
|
|
679
655
|
// a. if the chat is archived, and no further messages have been received -- simple, keep archived
|
|
680
656
|
// b. if the chat was archived, and the user received messages from the other person afterwards
|
|
681
|
-
//
|
|
682
|
-
//
|
|
657
|
+
// then the chat should be marked unarchved --
|
|
658
|
+
// we compare the timestamp of latest message from the other person to determine this
|
|
683
659
|
// 2. if the account unarchiveChats setting is false -- then it doesn't matter,
|
|
684
|
-
//
|
|
685
|
-
const archiveAction = action?.archiveChatAction
|
|
686
|
-
const isArchived = archiveAction
|
|
660
|
+
// it'll always take an app state action to mark in unarchived -- which we'll get anyway
|
|
661
|
+
const archiveAction = action?.archiveChatAction
|
|
662
|
+
const isArchived = archiveAction
|
|
663
|
+
? archiveAction.archived
|
|
664
|
+
: type === 'archive'
|
|
687
665
|
// // basically we don't need to fire an "archive" update if the chat is being marked unarchvied
|
|
688
666
|
// // this only applies for the initial sync
|
|
689
667
|
// if(isInitialSync && !isArchived) {
|
|
690
|
-
//
|
|
668
|
+
// isArchived = false
|
|
691
669
|
// }
|
|
692
|
-
const msgRange = !accountSettings?.unarchiveChats ? undefined : archiveAction?.messageRange
|
|
670
|
+
const msgRange = !accountSettings?.unarchiveChats ? undefined : archiveAction?.messageRange
|
|
693
671
|
// logger?.debug({ chat: id, syncAction }, 'message range archive')
|
|
694
|
-
ev.emit('chats.update', [
|
|
695
|
-
{
|
|
672
|
+
ev.emit('chats.update', [{
|
|
696
673
|
id,
|
|
697
674
|
archived: isArchived,
|
|
698
675
|
conditional: getChatUpdateConditional(id, msgRange)
|
|
699
|
-
}
|
|
700
|
-
]);
|
|
676
|
+
}])
|
|
701
677
|
}
|
|
702
678
|
else if (action?.markChatAsReadAction) {
|
|
703
|
-
const markReadAction = action.markChatAsReadAction
|
|
679
|
+
const markReadAction = action.markChatAsReadAction
|
|
704
680
|
// basically we don't need to fire an "read" update if the chat is being marked as read
|
|
705
681
|
// because the chat is read by default
|
|
706
682
|
// this only applies for the initial sync
|
|
707
|
-
const isNullUpdate = isInitialSync && markReadAction.read
|
|
708
|
-
ev.emit('chats.update', [
|
|
709
|
-
{
|
|
683
|
+
const isNullUpdate = isInitialSync && markReadAction.read
|
|
684
|
+
ev.emit('chats.update', [{
|
|
710
685
|
id,
|
|
711
686
|
unreadCount: isNullUpdate ? null : !!markReadAction?.read ? 0 : -1,
|
|
712
687
|
conditional: getChatUpdateConditional(id, markReadAction?.messageRange)
|
|
713
|
-
}
|
|
714
|
-
]);
|
|
688
|
+
}])
|
|
715
689
|
}
|
|
716
690
|
else if (action?.deleteMessageForMeAction || type === 'deleteMessageForMe') {
|
|
717
691
|
ev.emit('messages.delete', {
|
|
@@ -722,151 +696,114 @@ export const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) =
|
|
|
722
696
|
fromMe: fromMe === '1'
|
|
723
697
|
}
|
|
724
698
|
]
|
|
725
|
-
})
|
|
699
|
+
})
|
|
726
700
|
}
|
|
727
701
|
else if (action?.contactAction) {
|
|
728
|
-
|
|
729
|
-
|
|
702
|
+
ev.emit('contacts.upsert', [{
|
|
703
|
+
id,
|
|
704
|
+
name: action.contactAction.fullName,
|
|
705
|
+
lid: action.contactAction.lidJid || undefined,
|
|
706
|
+
phoneNumber: action.contactAction.pnJid || undefined
|
|
707
|
+
}])
|
|
730
708
|
}
|
|
731
709
|
else if (action?.pushNameSetting) {
|
|
732
|
-
const name = action?.pushNameSetting?.name
|
|
710
|
+
const name = action?.pushNameSetting?.name
|
|
733
711
|
if (name && me?.name !== name) {
|
|
734
|
-
ev.emit('creds.update', { me: { ...me, name } })
|
|
712
|
+
ev.emit('creds.update', { me: { ...me, name } })
|
|
735
713
|
}
|
|
736
714
|
}
|
|
737
715
|
else if (action?.pinAction) {
|
|
738
|
-
ev.emit('chats.update', [
|
|
739
|
-
{
|
|
716
|
+
ev.emit('chats.update', [{
|
|
740
717
|
id,
|
|
741
|
-
pinned: action.pinAction?.pinned ? toNumber(action.timestamp) : null,
|
|
718
|
+
pinned: action.pinAction?.pinned ? generics_1.toNumber(action.timestamp) : null,
|
|
742
719
|
conditional: getChatUpdateConditional(id, undefined)
|
|
743
|
-
}
|
|
744
|
-
]);
|
|
720
|
+
}])
|
|
745
721
|
}
|
|
746
722
|
else if (action?.unarchiveChatsSetting) {
|
|
747
|
-
const unarchiveChats = !!action.unarchiveChatsSetting.unarchiveChats
|
|
748
|
-
ev.emit('creds.update', { accountSettings: { unarchiveChats } })
|
|
749
|
-
logger?.info(`archive setting updated => '${action.unarchiveChatsSetting.unarchiveChats}'`)
|
|
723
|
+
const unarchiveChats = !!action.unarchiveChatsSetting.unarchiveChats
|
|
724
|
+
ev.emit('creds.update', { accountSettings: { unarchiveChats } })
|
|
725
|
+
logger?.info(`archive setting updated => '${action.unarchiveChatsSetting.unarchiveChats}'`)
|
|
750
726
|
if (accountSettings) {
|
|
751
|
-
accountSettings.unarchiveChats = unarchiveChats
|
|
727
|
+
accountSettings.unarchiveChats = unarchiveChats
|
|
752
728
|
}
|
|
753
729
|
}
|
|
754
730
|
else if (action?.starAction || type === 'star') {
|
|
755
|
-
let starred = action?.starAction?.starred
|
|
731
|
+
let starred = action?.starAction?.starred
|
|
756
732
|
if (typeof starred !== 'boolean') {
|
|
757
|
-
starred = syncAction.index[syncAction.index.length - 1] === '1'
|
|
733
|
+
starred = syncAction.index[syncAction.index.length - 1] === '1'
|
|
758
734
|
}
|
|
759
735
|
ev.emit('messages.update', [
|
|
760
736
|
{
|
|
761
737
|
key: { remoteJid: id, id: msgId, fromMe: fromMe === '1' },
|
|
762
738
|
update: { starred }
|
|
763
739
|
}
|
|
764
|
-
])
|
|
740
|
+
])
|
|
765
741
|
}
|
|
766
742
|
else if (action?.deleteChatAction || type === 'deleteChat') {
|
|
767
743
|
if (!isInitialSync) {
|
|
768
|
-
ev.emit('chats.delete', [id])
|
|
744
|
+
ev.emit('chats.delete', [id])
|
|
769
745
|
}
|
|
770
746
|
}
|
|
771
747
|
else if (action?.labelEditAction) {
|
|
772
|
-
const { name, color, deleted, predefinedId } = action.labelEditAction
|
|
748
|
+
const { name, color, deleted, predefinedId } = action.labelEditAction
|
|
773
749
|
ev.emit('labels.edit', {
|
|
774
|
-
id
|
|
750
|
+
id,
|
|
775
751
|
name: name,
|
|
776
752
|
color: color,
|
|
777
753
|
deleted: deleted,
|
|
778
754
|
predefinedId: predefinedId ? String(predefinedId) : undefined
|
|
779
|
-
})
|
|
755
|
+
})
|
|
780
756
|
}
|
|
781
757
|
else if (action?.labelAssociationAction) {
|
|
782
758
|
ev.emit('labels.association', {
|
|
783
|
-
type: action.labelAssociationAction.labeled
|
|
784
|
-
|
|
759
|
+
type: action.labelAssociationAction.labeled
|
|
760
|
+
? 'add'
|
|
761
|
+
: 'remove',
|
|
762
|
+
association: type === LabelAssociation_1.LabelAssociationType.Chat
|
|
785
763
|
? {
|
|
786
|
-
type: LabelAssociationType.Chat,
|
|
764
|
+
type: LabelAssociation_1.LabelAssociationType.Chat,
|
|
787
765
|
chatId: syncAction.index[2],
|
|
788
766
|
labelId: syncAction.index[1]
|
|
789
767
|
}
|
|
790
768
|
: {
|
|
791
|
-
type: LabelAssociationType.Message,
|
|
769
|
+
type: LabelAssociation_1.LabelAssociationType.Message,
|
|
792
770
|
chatId: syncAction.index[2],
|
|
793
771
|
messageId: syncAction.index[3],
|
|
794
772
|
labelId: syncAction.index[1]
|
|
795
773
|
}
|
|
796
|
-
})
|
|
797
|
-
}
|
|
798
|
-
else if (action?.localeSetting?.locale) {
|
|
799
|
-
ev.emit('settings.update', { setting: 'locale', value: action.localeSetting.locale });
|
|
800
|
-
}
|
|
801
|
-
else if (action?.timeFormatAction) {
|
|
802
|
-
ev.emit('settings.update', { setting: 'timeFormat', value: action.timeFormatAction });
|
|
803
|
-
}
|
|
804
|
-
else if (action?.pnForLidChatAction) {
|
|
805
|
-
if (action.pnForLidChatAction.pnJid) {
|
|
806
|
-
ev.emit('lid-mapping.update', { lid: id, pn: action.pnForLidChatAction.pnJid });
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
else if (action?.privacySettingRelayAllCalls) {
|
|
810
|
-
ev.emit('settings.update', {
|
|
811
|
-
setting: 'privacySettingRelayAllCalls',
|
|
812
|
-
value: action.privacySettingRelayAllCalls
|
|
813
|
-
});
|
|
814
|
-
}
|
|
815
|
-
else if (action?.statusPrivacy) {
|
|
816
|
-
ev.emit('settings.update', { setting: 'statusPrivacy', value: action.statusPrivacy });
|
|
817
|
-
}
|
|
818
|
-
else if (action?.lockChatAction) {
|
|
819
|
-
ev.emit('chats.lock', { id: id, locked: !!action.lockChatAction.locked });
|
|
820
|
-
}
|
|
821
|
-
else if (action?.privacySettingDisableLinkPreviewsAction) {
|
|
822
|
-
ev.emit('settings.update', {
|
|
823
|
-
setting: 'disableLinkPreviews',
|
|
824
|
-
value: action.privacySettingDisableLinkPreviewsAction
|
|
825
|
-
});
|
|
826
|
-
}
|
|
827
|
-
else if (action?.notificationActivitySettingAction?.notificationActivitySetting) {
|
|
828
|
-
ev.emit('settings.update', {
|
|
829
|
-
setting: 'notificationActivitySetting',
|
|
830
|
-
value: action.notificationActivitySettingAction.notificationActivitySetting
|
|
831
|
-
});
|
|
832
|
-
}
|
|
833
|
-
else if (action?.lidContactAction) {
|
|
834
|
-
ev.emit('contacts.upsert', [
|
|
835
|
-
{
|
|
836
|
-
id: id,
|
|
837
|
-
name: action.lidContactAction.fullName ||
|
|
838
|
-
action.lidContactAction.firstName ||
|
|
839
|
-
action.lidContactAction.username ||
|
|
840
|
-
undefined,
|
|
841
|
-
username: action.lidContactAction.username || undefined,
|
|
842
|
-
lid: id,
|
|
843
|
-
phoneNumber: undefined
|
|
844
|
-
}
|
|
845
|
-
]);
|
|
846
|
-
}
|
|
847
|
-
else if (action?.privacySettingChannelsPersonalisedRecommendationAction) {
|
|
848
|
-
ev.emit('settings.update', {
|
|
849
|
-
setting: 'channelsPersonalisedRecommendation',
|
|
850
|
-
value: action.privacySettingChannelsPersonalisedRecommendationAction
|
|
851
|
-
});
|
|
774
|
+
})
|
|
852
775
|
}
|
|
853
776
|
else {
|
|
854
|
-
logger?.debug({ syncAction, id }, 'unprocessable update')
|
|
777
|
+
logger?.debug({ syncAction, id }, 'unprocessable update')
|
|
855
778
|
}
|
|
856
779
|
function getChatUpdateConditional(id, msgRange) {
|
|
857
780
|
return isInitialSync
|
|
858
|
-
? data => {
|
|
859
|
-
const chat = data.historySets.chats[id] || data.chatUpserts[id]
|
|
781
|
+
? (data) => {
|
|
782
|
+
const chat = data.historySets.chats[id] || data.chatUpserts[id]
|
|
860
783
|
if (chat) {
|
|
861
|
-
return msgRange ? isValidPatchBasedOnMessageRange(chat, msgRange) : true
|
|
784
|
+
return msgRange ? isValidPatchBasedOnMessageRange(chat, msgRange) : true
|
|
862
785
|
}
|
|
863
786
|
}
|
|
864
|
-
: undefined
|
|
787
|
+
: undefined
|
|
865
788
|
}
|
|
866
789
|
function isValidPatchBasedOnMessageRange(chat, msgRange) {
|
|
867
|
-
const lastMsgTimestamp = Number(msgRange?.lastMessageTimestamp || msgRange?.lastSystemMessageTimestamp || 0)
|
|
868
|
-
const chatLastMsgTimestamp = Number(chat?.lastMessageRecvTimestamp || 0)
|
|
869
|
-
return lastMsgTimestamp >= chatLastMsgTimestamp
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
|
|
790
|
+
const lastMsgTimestamp = Number(msgRange?.lastMessageTimestamp || msgRange?.lastSystemMessageTimestamp || 0)
|
|
791
|
+
const chatLastMsgTimestamp = Number(chat?.lastMessageRecvTimestamp || 0)
|
|
792
|
+
return lastMsgTimestamp >= chatLastMsgTimestamp
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
module.exports = {
|
|
797
|
+
mutationKeys,
|
|
798
|
+
newLTHashState,
|
|
799
|
+
encodeSyncdPatch,
|
|
800
|
+
decodeSyncdMutations,
|
|
801
|
+
decodeSyncdPatch,
|
|
802
|
+
extractSyncdPatches,
|
|
803
|
+
downloadExternalBlob,
|
|
804
|
+
downloadExternalPatch,
|
|
805
|
+
decodeSyncdSnapshot,
|
|
806
|
+
decodePatches,
|
|
807
|
+
chatModificationToAppPatch,
|
|
808
|
+
processSyncAction
|
|
809
|
+
}
|