@hansaka02/baileys 7.3.2 → 7.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +247 -203
- package/lib/Defaults/connection.js +51 -0
- package/lib/Defaults/constants.js +62 -0
- package/lib/Defaults/history.js +17 -0
- package/lib/Defaults/index.js +36 -142
- package/lib/Defaults/media.js +48 -0
- package/lib/Defaults/prefix.js +18 -0
- package/lib/Signal/Group/group-session-builder.js +10 -42
- package/lib/Signal/Group/group_cipher.js +9 -6
- package/lib/Signal/Group/index.js +39 -53
- package/lib/Signal/Group/keyhelper.js +8 -41
- package/lib/Signal/Group/sender-chain-key.js +4 -4
- package/lib/Signal/Group/sender-key-distribution-message.js +5 -5
- package/lib/Signal/Group/sender-key-message.js +12 -8
- package/lib/Signal/Group/sender-key-record.js +7 -7
- package/lib/Signal/Group/sender-key-state.js +4 -4
- package/lib/Signal/Group/sender-message-key.js +2 -2
- package/lib/Signal/libsignal.js +45 -69
- package/lib/Signal/lid-mapping.js +15 -11
- package/lib/Socket/Client/types.js +2 -2
- package/lib/Socket/Client/websocket.js +16 -14
- package/lib/Socket/business.js +41 -32
- package/lib/Socket/chats.js +123 -98
- package/lib/Socket/community.js +50 -40
- package/lib/Socket/groups.js +59 -47
- package/lib/Socket/index.js +4 -4
- package/lib/Socket/messages-recv.js +219 -172
- package/lib/Socket/messages-send.js +187 -143
- package/lib/Socket/newsletter.js +61 -47
- package/lib/Socket/socket.js +133 -90
- package/lib/Socket/usync.js +6 -6
- package/lib/Store/index.js +27 -11
- package/lib/Store/make-cache-manager-store.js +14 -15
- package/lib/Store/make-in-memory-store.js +28 -24
- package/lib/Types/LabelAssociation.js +2 -2
- package/lib/Types/Message.js +6 -6
- package/lib/Types/MexUpdates.js +5 -5
- package/lib/Types/State.js +4 -4
- package/lib/Types/index.js +28 -12
- package/lib/Utils/auth-utils.js +28 -26
- package/lib/Utils/baileys-event-stream.js +68 -69
- package/lib/Utils/business.js +63 -53
- package/lib/Utils/chat-utils.js +81 -71
- package/lib/Utils/crypto.js +25 -45
- package/lib/Utils/decode-wa-message.js +319 -311
- package/lib/Utils/event-buffer.js +21 -22
- package/lib/Utils/generics.js +65 -82
- package/lib/Utils/history.js +21 -21
- package/lib/Utils/index.js +27 -13
- package/lib/Utils/link-preview.js +7 -30
- package/lib/Utils/logger.js +5 -5
- package/lib/Utils/lt-hash.js +3 -3
- package/lib/Utils/message-retry-manager.js +4 -4
- package/lib/Utils/messages-media.js +104 -109
- package/lib/Utils/messages.js +203 -171
- package/lib/Utils/noise-handler.js +28 -19
- package/lib/Utils/process-message.js +111 -96
- package/lib/Utils/signal.js +36 -25
- package/lib/Utils/use-multi-file-auth-state.js +18 -22
- package/lib/Utils/validate-connection.js +52 -45
- package/lib/WABinary/decode.js +6 -32
- package/lib/WABinary/encode.js +3 -29
- package/lib/WABinary/generic-utils.js +4 -4
- package/lib/WABinary/index.js +27 -11
- package/lib/WAM/encode.js +16 -8
- package/lib/WAM/index.js +27 -11
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +20 -16
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +2 -2
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +7 -4
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +2 -2
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js +0 -2
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +2 -2
- package/lib/WAUSync/Protocols/index.js +27 -11
- package/lib/WAUSync/USyncQuery.js +17 -10
- package/lib/WAUSync/index.js +27 -11
- package/lib/index.js +60 -31
- package/package.json +8 -14
- package/WAProto/AICommon/AICommon.d.ts +0 -11702
- package/WAProto/Adv/Adv.d.ts +0 -643
- package/WAProto/BotMetadata/BotMetadata.d.ts +0 -5654
- package/WAProto/Cert/Cert.d.ts +0 -613
- package/WAProto/ChatLockSettings/ChatLockSettings.d.ts +0 -476
- package/WAProto/CompanionReg/CompanionReg.d.ts +0 -1361
- package/WAProto/DeviceCapabilities/DeviceCapabilities.d.ts +0 -577
- package/WAProto/E2E/E2E.d.ts +0 -41724
- package/WAProto/Ephemeral/Ephemeral.d.ts +0 -114
- package/WAProto/HistorySync/HistorySync.d.ts +0 -51700
- package/WAProto/LidMigrationSyncPayload/LidMigrationSyncPayload.d.ts +0 -229
- package/WAProto/MdStorageChatRowOpaqueData/MdStorageChatRowOpaqueData.d.ts +0 -583
- package/WAProto/MdStorageMsgRowOpaqueData/MdStorageMsgRowOpaqueData.d.ts +0 -42897
- package/WAProto/MmsRetry/MmsRetry.d.ts +0 -243
- package/WAProto/Protocol/Protocol.d.ts +0 -270
- package/WAProto/Reporting/Reporting.d.ts +0 -371
- package/WAProto/ServerSync/ServerSync.d.ts +0 -1285
- package/WAProto/SignalLocalStorageProtocol/SignalLocalStorageProtocol.d.ts +0 -1868
- package/WAProto/SignalWhisperTextProtocol/SignalWhisperTextProtocol.d.ts +0 -767
- package/WAProto/StatusAttributions/StatusAttributions.d.ts +0 -1027
- package/WAProto/SyncAction/SyncAction.d.ts +0 -11193
- package/WAProto/UserPassword/UserPassword.d.ts +0 -363
- package/WAProto/VnameCert/VnameCert.d.ts +0 -821
- package/WAProto/Wa6/Wa6.d.ts +0 -2128
- package/WAProto/Web/Web.d.ts +0 -46383
- package/WAProto/index.d.ts +0 -55
- package/lib/Defaults/index.d.ts +0 -77
- package/lib/Signal/Group/ciphertext-message.d.ts +0 -9
- package/lib/Signal/Group/group-session-builder.d.ts +0 -17
- package/lib/Signal/Group/group_cipher.d.ts +0 -19
- package/lib/Signal/Group/index.d.ts +0 -11
- package/lib/Signal/Group/keyhelper.d.ts +0 -16
- package/lib/Signal/Group/sender-chain-key.d.ts +0 -14
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -17
- package/lib/Signal/Group/sender-key-message.d.ts +0 -19
- package/lib/Signal/Group/sender-key-name.d.ts +0 -19
- package/lib/Signal/Group/sender-key-record.d.ts +0 -32
- package/lib/Signal/Group/sender-key-state.d.ts +0 -44
- package/lib/Signal/Group/sender-message-key.d.ts +0 -11
- package/lib/Signal/libsignal.d.ts +0 -8
- package/lib/Signal/lid-mapping.d.ts +0 -28
- package/lib/Socket/Client/index.d.ts +0 -2
- package/lib/Socket/Client/types.d.ts +0 -16
- package/lib/Socket/Client/websocket.d.ts +0 -13
- package/lib/Socket/business.d.ts +0 -187
- package/lib/Socket/chats.d.ts +0 -97
- package/lib/Socket/community.d.ts +0 -129
- package/lib/Socket/groups.d.ts +0 -129
- package/lib/Socket/index.d.ts +0 -191
- package/lib/Socket/messages-recv.d.ts +0 -174
- package/lib/Socket/messages-send.d.ts +0 -165
- package/lib/Socket/newsletter.d.ts +0 -145
- package/lib/Socket/socket.d.ts +0 -45
- package/lib/Socket/usync.d.ts +0 -37
- package/lib/Store/index.d.ts +0 -4
- package/lib/Store/make-cache-manager-store.d.ts +0 -14
- package/lib/Store/make-in-memory-store.d.ts +0 -123
- package/lib/Store/make-ordered-dictionary.d.ts +0 -12
- package/lib/Store/object-repository.d.ts +0 -10
- package/lib/Types/Auth.d.ts +0 -121
- package/lib/Types/Bussiness.d.ts +0 -28
- package/lib/Types/Call.d.ts +0 -14
- package/lib/Types/Chat.d.ts +0 -143
- package/lib/Types/Contact.d.ts +0 -23
- package/lib/Types/Events.d.ts +0 -226
- package/lib/Types/GroupMetadata.d.ts +0 -66
- package/lib/Types/Label.d.ts +0 -48
- package/lib/Types/LabelAssociation.d.ts +0 -35
- package/lib/Types/Message.d.ts +0 -484
- package/lib/Types/MexUpdates.d.ts +0 -9
- package/lib/Types/Newsletter.d.ts +0 -109
- package/lib/Types/Product.d.ts +0 -92
- package/lib/Types/Signal.d.ts +0 -98
- package/lib/Types/Socket.d.ts +0 -141
- package/lib/Types/State.d.ts +0 -41
- package/lib/Types/USync.d.ts +0 -26
- package/lib/Types/index.d.ts +0 -80
- package/lib/Utils/auth-utils.d.ts +0 -21
- package/lib/Utils/baileys-event-stream.d.ts +0 -18
- package/lib/Utils/business.d.ts +0 -29
- package/lib/Utils/chat-utils.d.ts +0 -82
- package/lib/Utils/crypto.d.ts +0 -56
- package/lib/Utils/decode-wa-message.d.ts +0 -53
- package/lib/Utils/event-buffer.d.ts +0 -39
- package/lib/Utils/generics.d.ts +0 -117
- package/lib/Utils/history.d.ts +0 -23
- package/lib/Utils/index.d.ts +0 -20
- package/lib/Utils/link-preview.d.ts +0 -23
- package/lib/Utils/logger.d.ts +0 -13
- package/lib/Utils/lt-hash.d.ts +0 -14
- package/lib/Utils/make-mutex.d.ts +0 -9
- package/lib/Utils/message-retry-manager.d.ts +0 -88
- package/lib/Utils/messages-media.d.ts +0 -135
- package/lib/Utils/messages.d.ts +0 -105
- package/lib/Utils/noise-handler.d.ts +0 -20
- package/lib/Utils/process-message.d.ts +0 -49
- package/lib/Utils/signal.d.ts +0 -42
- package/lib/Utils/use-mongo-file-auth-state.d.ts +0 -6
- package/lib/Utils/use-mongo-file-auth-state.js +0 -84
- package/lib/Utils/use-multi-file-auth-state.d.ts +0 -13
- package/lib/Utils/use-single-file-auth-state.d.ts +0 -13
- package/lib/Utils/use-single-file-auth-state.js +0 -80
- package/lib/Utils/validate-connection.d.ts +0 -13
- package/lib/WABinary/constants.d.ts +0 -30
- package/lib/WABinary/decode.d.ts +0 -9
- package/lib/WABinary/encode.d.ts +0 -3
- package/lib/WABinary/generic-utils.d.ts +0 -28
- package/lib/WABinary/index.d.ts +0 -5
- package/lib/WABinary/jid-utils.d.ts +0 -58
- package/lib/WABinary/types.d.ts +0 -22
- package/lib/WAM/BinaryInfo.d.ts +0 -16
- package/lib/WAM/constants.d.ts +0 -47
- package/lib/WAM/encode.d.ts +0 -3
- package/lib/WAM/index.d.ts +0 -3
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts +0 -28
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -10
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -26
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -14
- package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts +0 -10
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -14
- package/lib/WAUSync/Protocols/index.d.ts +0 -6
- package/lib/WAUSync/USyncQuery.d.ts +0 -31
- package/lib/WAUSync/USyncUser.d.ts +0 -12
- package/lib/WAUSync/index.d.ts +0 -3
- package/lib/index.d.ts +0 -13
package/lib/Utils/business.js
CHANGED
|
@@ -2,33 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true })
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
const { Boom } = require("@hapi/boom")
|
|
6
|
+
const { createHash } = require("crypto")
|
|
7
|
+
const { join } = require("path")
|
|
8
|
+
const { tmpdir } = require("os")
|
|
9
|
+
const {
|
|
10
|
+
promises,
|
|
11
|
+
createWriteStream
|
|
12
|
+
} = require("fs")
|
|
13
|
+
const {
|
|
14
|
+
getBinaryNodeChild,
|
|
15
|
+
getBinaryNodeChildren,
|
|
16
|
+
getBinaryNodeChildString
|
|
17
|
+
} = require("../WABinary")
|
|
18
|
+
const {
|
|
19
|
+
getStream,
|
|
20
|
+
getUrlFromDirectPath
|
|
21
|
+
} = require("./messages-media")
|
|
22
|
+
const { generateMessageID } = require("./generics")
|
|
13
23
|
|
|
14
24
|
const parseCatalogNode = (node) => {
|
|
15
|
-
const catalogNode =
|
|
16
|
-
const products =
|
|
17
|
-
const paging =
|
|
25
|
+
const catalogNode = getBinaryNodeChild(node, 'product_catalog')
|
|
26
|
+
const products = getBinaryNodeChildren(catalogNode, 'product').map(parseProductNode)
|
|
27
|
+
const paging = getBinaryNodeChild(catalogNode, 'paging')
|
|
18
28
|
return {
|
|
19
29
|
products,
|
|
20
30
|
nextPageCursor: paging
|
|
21
|
-
?
|
|
31
|
+
? getBinaryNodeChildString(paging, 'after')
|
|
22
32
|
: undefined
|
|
23
33
|
}
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
const parseCollectionsNode = (node) => {
|
|
27
|
-
const collectionsNode =
|
|
28
|
-
const collections =
|
|
29
|
-
const id =
|
|
30
|
-
const name =
|
|
31
|
-
const products =
|
|
37
|
+
const collectionsNode = getBinaryNodeChild(node, 'collections')
|
|
38
|
+
const collections = getBinaryNodeChildren(collectionsNode, 'collection').map(collectionNode => {
|
|
39
|
+
const id = getBinaryNodeChildString(collectionNode, 'id')
|
|
40
|
+
const name = getBinaryNodeChildString(collectionNode, 'name')
|
|
41
|
+
const products = getBinaryNodeChildren(collectionNode, 'product').map(parseProductNode)
|
|
32
42
|
return {
|
|
33
43
|
id,
|
|
34
44
|
name,
|
|
@@ -42,23 +52,23 @@ const parseCollectionsNode = (node) => {
|
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
const parseOrderDetailsNode = (node) => {
|
|
45
|
-
const orderNode =
|
|
46
|
-
const products =
|
|
47
|
-
const imageNode =
|
|
55
|
+
const orderNode = getBinaryNodeChild(node, 'order')
|
|
56
|
+
const products = getBinaryNodeChildren(orderNode, 'product').map(productNode => {
|
|
57
|
+
const imageNode = getBinaryNodeChild(productNode, 'image')
|
|
48
58
|
return {
|
|
49
|
-
id:
|
|
50
|
-
name:
|
|
51
|
-
imageUrl:
|
|
52
|
-
price: +
|
|
53
|
-
currency:
|
|
54
|
-
quantity: +
|
|
59
|
+
id: getBinaryNodeChildString(productNode, 'id'),
|
|
60
|
+
name: getBinaryNodeChildString(productNode, 'name'),
|
|
61
|
+
imageUrl: getBinaryNodeChildString(imageNode, 'url'),
|
|
62
|
+
price: +getBinaryNodeChildString(productNode, 'price'),
|
|
63
|
+
currency: getBinaryNodeChildString(productNode, 'currency'),
|
|
64
|
+
quantity: +getBinaryNodeChildString(productNode, 'quantity')
|
|
55
65
|
}
|
|
56
66
|
})
|
|
57
|
-
const priceNode =
|
|
67
|
+
const priceNode = getBinaryNodeChild(orderNode, 'price')
|
|
58
68
|
const orderDetails = {
|
|
59
69
|
price: {
|
|
60
|
-
total: +
|
|
61
|
-
currency:
|
|
70
|
+
total: +getBinaryNodeChildString(priceNode, 'total'),
|
|
71
|
+
currency: getBinaryNodeChildString(priceNode, 'currency'),
|
|
62
72
|
},
|
|
63
73
|
products
|
|
64
74
|
}
|
|
@@ -102,7 +112,7 @@ const toProductNode = (productId, product) => {
|
|
|
102
112
|
attrs: {},
|
|
103
113
|
content: product.images.map(img => {
|
|
104
114
|
if (!('url' in img)) {
|
|
105
|
-
throw new
|
|
115
|
+
throw new Boom('Expected img for product to already be uploaded', { statusCode: 400 })
|
|
106
116
|
}
|
|
107
117
|
return {
|
|
108
118
|
tag: 'image',
|
|
@@ -163,23 +173,23 @@ const toProductNode = (productId, product) => {
|
|
|
163
173
|
|
|
164
174
|
const parseProductNode = (productNode) => {
|
|
165
175
|
const isHidden = productNode.attrs.is_hidden === 'true'
|
|
166
|
-
const id =
|
|
167
|
-
const mediaNode =
|
|
168
|
-
const statusInfoNode =
|
|
176
|
+
const id = getBinaryNodeChildString(productNode, 'id')
|
|
177
|
+
const mediaNode = getBinaryNodeChild(productNode, 'media')
|
|
178
|
+
const statusInfoNode = getBinaryNodeChild(productNode, 'status_info')
|
|
169
179
|
const product = {
|
|
170
180
|
id,
|
|
171
181
|
imageUrls: parseImageUrls(mediaNode),
|
|
172
182
|
reviewStatus: {
|
|
173
|
-
whatsapp:
|
|
183
|
+
whatsapp: getBinaryNodeChildString(statusInfoNode, 'status'),
|
|
174
184
|
},
|
|
175
185
|
availability: 'in stock',
|
|
176
|
-
name:
|
|
177
|
-
retailerId:
|
|
178
|
-
url:
|
|
179
|
-
description:
|
|
180
|
-
price: +
|
|
181
|
-
currency:
|
|
182
|
-
isHidden
|
|
186
|
+
name: getBinaryNodeChildString(productNode, 'name'),
|
|
187
|
+
retailerId: getBinaryNodeChildString(productNode, 'retailer_id'),
|
|
188
|
+
url: getBinaryNodeChildString(productNode, 'url'),
|
|
189
|
+
description: getBinaryNodeChildString(productNode, 'description'),
|
|
190
|
+
price: +getBinaryNodeChildString(productNode, 'price'),
|
|
191
|
+
currency: getBinaryNodeChildString(productNode, 'currency'),
|
|
192
|
+
isHidden
|
|
183
193
|
}
|
|
184
194
|
return product
|
|
185
195
|
}
|
|
@@ -206,10 +216,10 @@ const uploadingNecessaryImages = async (images, waUploadToServer, timeoutMs = 30
|
|
|
206
216
|
return { url }
|
|
207
217
|
}
|
|
208
218
|
}
|
|
209
|
-
const { stream } = await
|
|
210
|
-
const hasher =
|
|
211
|
-
const filePath =
|
|
212
|
-
const encFileWriteStream =
|
|
219
|
+
const { stream } = await getStream(img)
|
|
220
|
+
const hasher = createHash('sha256')
|
|
221
|
+
const filePath = join(tmpdir(), 'img' + generateMessageID())
|
|
222
|
+
const encFileWriteStream = createWriteStream(filePath)
|
|
213
223
|
for await (const block of stream) {
|
|
214
224
|
hasher.update(block)
|
|
215
225
|
encFileWriteStream.write(block)
|
|
@@ -220,27 +230,27 @@ const uploadingNecessaryImages = async (images, waUploadToServer, timeoutMs = 30
|
|
|
220
230
|
fileEncSha256B64: sha,
|
|
221
231
|
timeoutMs
|
|
222
232
|
})
|
|
223
|
-
await
|
|
233
|
+
await promises
|
|
224
234
|
.unlink(filePath)
|
|
225
235
|
.catch(err => console.log('Error deleting temp file ', err))
|
|
226
|
-
return { url:
|
|
236
|
+
return { url: getUrlFromDirectPath(directPath) }
|
|
227
237
|
}))
|
|
228
238
|
return results
|
|
229
239
|
}
|
|
230
240
|
|
|
231
241
|
const parseImageUrls = (mediaNode) => {
|
|
232
|
-
const imgNode =
|
|
242
|
+
const imgNode = getBinaryNodeChild(mediaNode, 'image')
|
|
233
243
|
return {
|
|
234
|
-
requested:
|
|
235
|
-
original:
|
|
244
|
+
requested: getBinaryNodeChildString(imgNode, 'request_image_url'),
|
|
245
|
+
original: getBinaryNodeChildString(imgNode, 'original_image_url')
|
|
236
246
|
}
|
|
237
247
|
}
|
|
238
248
|
|
|
239
249
|
const parseStatusInfo = (mediaNode) => {
|
|
240
|
-
const node =
|
|
250
|
+
const node = getBinaryNodeChild(mediaNode, 'status_info')
|
|
241
251
|
return {
|
|
242
|
-
status:
|
|
243
|
-
canAppeal:
|
|
252
|
+
status: getBinaryNodeChildString(node, 'status'),
|
|
253
|
+
canAppeal: getBinaryNodeChildString(node, 'can_appeal') === 'true',
|
|
244
254
|
}
|
|
245
255
|
}
|
|
246
256
|
|
package/lib/Utils/chat-utils.js
CHANGED
|
@@ -2,17 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true })
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
const { Boom } = require("@hapi/boom")
|
|
6
|
+
const { proto } = require("../../WAProto")
|
|
7
|
+
const { LabelAssociationType } = require("../Types/LabelAssociation")
|
|
8
|
+
const {
|
|
9
|
+
getBinaryNodeChild,
|
|
10
|
+
getBinaryNodeChildren,
|
|
11
|
+
isJidGroup,
|
|
12
|
+
jidNormalizedUser
|
|
13
|
+
} = require("../WABinary")
|
|
14
|
+
const {
|
|
15
|
+
hkdf,
|
|
16
|
+
hmacSign,
|
|
17
|
+
aesEncrypt,
|
|
18
|
+
aesDecrypt
|
|
19
|
+
} = require("./crypto")
|
|
20
|
+
const { toNumber } = require("./generics")
|
|
21
|
+
const { LT_HASH_ANTI_TAMPERING } = require("./lt-hash")
|
|
22
|
+
const { downloadContentFromMessage } = require("./messages-media")
|
|
13
23
|
|
|
14
24
|
const mutationKeys = async (keydata) => {
|
|
15
|
-
const expanded = await
|
|
25
|
+
const expanded = await hkdf(keydata, 160, { info: 'WhatsApp Mutation Keys' })
|
|
16
26
|
return {
|
|
17
27
|
indexKey: expanded.slice(0, 32),
|
|
18
28
|
valueEncryptionKey: expanded.slice(32, 64),
|
|
@@ -26,10 +36,10 @@ const generateMac = (operation, data, keyId, key) => {
|
|
|
26
36
|
const getKeyData = () => {
|
|
27
37
|
let r
|
|
28
38
|
switch (operation) {
|
|
29
|
-
case
|
|
39
|
+
case proto.SyncdMutation.SyncdOperation.SET:
|
|
30
40
|
r = 0x01
|
|
31
41
|
break
|
|
32
|
-
case
|
|
42
|
+
case proto.SyncdMutation.SyncdOperation.REMOVE:
|
|
33
43
|
r = 0x02
|
|
34
44
|
break
|
|
35
45
|
}
|
|
@@ -40,7 +50,7 @@ const generateMac = (operation, data, keyId, key) => {
|
|
|
40
50
|
const last = Buffer.alloc(8) // 8 bytes
|
|
41
51
|
last.set([keyData.length], last.length - 1)
|
|
42
52
|
const total = Buffer.concat([keyData, data, last])
|
|
43
|
-
const hmac =
|
|
53
|
+
const hmac = hmacSign(total, key, 'sha512')
|
|
44
54
|
return hmac.slice(0, 32)
|
|
45
55
|
}
|
|
46
56
|
|
|
@@ -58,9 +68,9 @@ const makeLtHashGenerator = ({ indexValueMap, hash }) => {
|
|
|
58
68
|
mix: ({ indexMac, valueMac, operation }) => {
|
|
59
69
|
const indexMacBase64 = Buffer.from(indexMac).toString('base64')
|
|
60
70
|
const prevOp = indexValueMap[indexMacBase64]
|
|
61
|
-
if (operation ===
|
|
71
|
+
if (operation === proto.SyncdMutation.SyncdOperation.REMOVE) {
|
|
62
72
|
if (!prevOp) {
|
|
63
|
-
throw new
|
|
73
|
+
throw new Boom('tried remove, but no previous op', { data: { indexMac, valueMac } })
|
|
64
74
|
}
|
|
65
75
|
// remove from index value mac, since this mutation is erased
|
|
66
76
|
delete indexValueMap[indexMacBase64]
|
|
@@ -76,7 +86,7 @@ const makeLtHashGenerator = ({ indexValueMap, hash }) => {
|
|
|
76
86
|
},
|
|
77
87
|
finish: async () => {
|
|
78
88
|
const hashArrayBuffer = new Uint8Array(hash).buffer
|
|
79
|
-
const result = await
|
|
89
|
+
const result = await LT_HASH_ANTI_TAMPERING.subtractThenAdd(hashArrayBuffer, addBuffs, subBuffs)
|
|
80
90
|
const buffer = Buffer.from(result)
|
|
81
91
|
return {
|
|
82
92
|
hash: buffer,
|
|
@@ -92,7 +102,7 @@ const generateSnapshotMac = (lthash, version, name, key) => {
|
|
|
92
102
|
to64BitNetworkOrder(version),
|
|
93
103
|
Buffer.from(name, 'utf-8')
|
|
94
104
|
])
|
|
95
|
-
return
|
|
105
|
+
return hmacSign(total, key, 'sha256')
|
|
96
106
|
}
|
|
97
107
|
|
|
98
108
|
const generatePatchMac = (snapshotMac, valueMacs, version, type, key) => {
|
|
@@ -102,7 +112,7 @@ const generatePatchMac = (snapshotMac, valueMacs, version, type, key) => {
|
|
|
102
112
|
to64BitNetworkOrder(version),
|
|
103
113
|
Buffer.from(type, 'utf-8')
|
|
104
114
|
])
|
|
105
|
-
return
|
|
115
|
+
return hmacSign(total, key)
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
const newLTHashState = () => ({ version: 0, hash: Buffer.alloc(128), indexValueMap: {} })
|
|
@@ -110,22 +120,22 @@ const newLTHashState = () => ({ version: 0, hash: Buffer.alloc(128), indexValueM
|
|
|
110
120
|
const encodeSyncdPatch = async ({ type, index, syncAction, apiVersion, operation }, myAppStateKeyId, state, getAppStateSyncKey) => {
|
|
111
121
|
const key = !!myAppStateKeyId ? await getAppStateSyncKey(myAppStateKeyId) : undefined
|
|
112
122
|
if (!key) {
|
|
113
|
-
throw new
|
|
123
|
+
throw new Boom(`myAppStateKey ("${myAppStateKeyId}") not present`, { statusCode: 404 })
|
|
114
124
|
}
|
|
115
125
|
const encKeyId = Buffer.from(myAppStateKeyId, 'base64')
|
|
116
126
|
state = { ...state, indexValueMap: { ...state.indexValueMap } }
|
|
117
127
|
const indexBuffer = Buffer.from(JSON.stringify(index))
|
|
118
|
-
const dataProto =
|
|
128
|
+
const dataProto = proto.SyncActionData.fromObject({
|
|
119
129
|
index: indexBuffer,
|
|
120
130
|
value: syncAction,
|
|
121
131
|
padding: new Uint8Array(0),
|
|
122
132
|
version: apiVersion
|
|
123
133
|
})
|
|
124
|
-
const encoded =
|
|
134
|
+
const encoded = proto.SyncActionData.encode(dataProto).finish()
|
|
125
135
|
const keyValue = await mutationKeys(key.keyData)
|
|
126
|
-
const encValue =
|
|
136
|
+
const encValue = aesEncrypt(encoded, keyValue.valueEncryptionKey)
|
|
127
137
|
const valueMac = generateMac(operation, encValue, encKeyId, keyValue.valueMacKey)
|
|
128
|
-
const indexMac =
|
|
138
|
+
const indexMac = hmacSign(indexBuffer, keyValue.indexKey)
|
|
129
139
|
// update LT hash
|
|
130
140
|
const generator = makeLtHashGenerator(state)
|
|
131
141
|
generator.mix({ indexMac, valueMac, operation })
|
|
@@ -164,7 +174,7 @@ const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncK
|
|
|
164
174
|
for (const msgMutation of msgMutations) {
|
|
165
175
|
// if it's a syncdmutation, get the operation property
|
|
166
176
|
// otherwise, if it's only a record -- it'll be a SET mutation
|
|
167
|
-
const operation = 'operation' in msgMutation ? msgMutation.operation :
|
|
177
|
+
const operation = 'operation' in msgMutation ? msgMutation.operation : proto.SyncdMutation.SyncdOperation.SET
|
|
168
178
|
const record = ('record' in msgMutation && !!msgMutation.record) ? msgMutation.record : msgMutation
|
|
169
179
|
const key = await getKey(record.keyId.id)
|
|
170
180
|
const content = Buffer.from(record.value.blob)
|
|
@@ -173,15 +183,15 @@ const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncK
|
|
|
173
183
|
if (validateMacs) {
|
|
174
184
|
const contentHmac = generateMac(operation, encContent, record.keyId.id, key.valueMacKey)
|
|
175
185
|
if (Buffer.compare(contentHmac, ogValueMac) !== 0) {
|
|
176
|
-
throw new
|
|
186
|
+
throw new Boom('HMAC content verification failed')
|
|
177
187
|
}
|
|
178
188
|
}
|
|
179
|
-
const result =
|
|
180
|
-
const syncAction =
|
|
189
|
+
const result = aesDecrypt(encContent, key.valueEncryptionKey)
|
|
190
|
+
const syncAction = proto.SyncActionData.decode(result)
|
|
181
191
|
if (validateMacs) {
|
|
182
|
-
const hmac =
|
|
192
|
+
const hmac = hmacSign(syncAction.index, key.indexKey)
|
|
183
193
|
if (Buffer.compare(hmac, record.index.blob) !== 0) {
|
|
184
|
-
throw new
|
|
194
|
+
throw new Boom('HMAC index verification failed')
|
|
185
195
|
}
|
|
186
196
|
}
|
|
187
197
|
const indexStr = Buffer.from(syncAction.index).toString()
|
|
@@ -197,7 +207,7 @@ const decodeSyncdMutations = async (msgMutations, initialState, getAppStateSyncK
|
|
|
197
207
|
const base64Key = Buffer.from(keyId).toString('base64')
|
|
198
208
|
const keyEnc = await getAppStateSyncKey(base64Key)
|
|
199
209
|
if (!keyEnc) {
|
|
200
|
-
throw new
|
|
210
|
+
throw new Boom(`failed to find key "${base64Key}" to decode mutation`, { statusCode: 404, data: { msgMutations } })
|
|
201
211
|
}
|
|
202
212
|
return mutationKeys(keyEnc.keyData)
|
|
203
213
|
}
|
|
@@ -208,13 +218,13 @@ const decodeSyncdPatch = async (msg, name, initialState, getAppStateSyncKey, onM
|
|
|
208
218
|
const base64Key = Buffer.from(msg.keyId.id).toString('base64')
|
|
209
219
|
const mainKeyObj = await getAppStateSyncKey(base64Key)
|
|
210
220
|
if (!mainKeyObj) {
|
|
211
|
-
throw new
|
|
221
|
+
throw new Boom(`failed to find key "${base64Key}" to decode patch`, { statusCode: 404, data: { msg } })
|
|
212
222
|
}
|
|
213
223
|
const mainKey = await mutationKeys(mainKeyObj.keyData)
|
|
214
224
|
const mutationmacs = msg.mutations.map(mutation => mutation.record.value.blob.slice(-32))
|
|
215
|
-
const patchMac = generatePatchMac(msg.snapshotMac, mutationmacs,
|
|
225
|
+
const patchMac = generatePatchMac(msg.snapshotMac, mutationmacs, toNumber(msg.version.version), name, mainKey.patchMacKey)
|
|
216
226
|
if (Buffer.compare(patchMac, msg.patchMac) !== 0) {
|
|
217
|
-
throw new
|
|
227
|
+
throw new Boom('Invalid patch mac')
|
|
218
228
|
}
|
|
219
229
|
}
|
|
220
230
|
const result = await decodeSyncdMutations(msg.mutations, initialState, getAppStateSyncKey, onMutation, validateMacs)
|
|
@@ -222,13 +232,13 @@ const decodeSyncdPatch = async (msg, name, initialState, getAppStateSyncKey, onM
|
|
|
222
232
|
}
|
|
223
233
|
|
|
224
234
|
const extractSyncdPatches = async (result, options) => {
|
|
225
|
-
const syncNode =
|
|
226
|
-
const collectionNodes =
|
|
235
|
+
const syncNode = getBinaryNodeChild(result, 'sync')
|
|
236
|
+
const collectionNodes = getBinaryNodeChildren(syncNode, 'collection')
|
|
227
237
|
const final = {}
|
|
228
238
|
await Promise.all(collectionNodes.map(async (collectionNode) => {
|
|
229
|
-
const patchesNode =
|
|
230
|
-
const patches =
|
|
231
|
-
const snapshotNode =
|
|
239
|
+
const patchesNode = getBinaryNodeChild(collectionNode, 'patches')
|
|
240
|
+
const patches = getBinaryNodeChildren(patchesNode || collectionNode, 'patch')
|
|
241
|
+
const snapshotNode = getBinaryNodeChild(collectionNode, 'snapshot')
|
|
232
242
|
const syncds = []
|
|
233
243
|
const name = collectionNode.attrs.name
|
|
234
244
|
const hasMorePatches = collectionNode.attrs.has_more_patches === 'true'
|
|
@@ -237,16 +247,16 @@ const extractSyncdPatches = async (result, options) => {
|
|
|
237
247
|
if (!Buffer.isBuffer(snapshotNode)) {
|
|
238
248
|
snapshotNode.content = Buffer.from(Object.values(snapshotNode.content))
|
|
239
249
|
}
|
|
240
|
-
const blobRef =
|
|
250
|
+
const blobRef = proto.ExternalBlobReference.decode(snapshotNode.content)
|
|
241
251
|
const data = await downloadExternalBlob(blobRef, options)
|
|
242
|
-
snapshot =
|
|
252
|
+
snapshot = proto.SyncdSnapshot.decode(data)
|
|
243
253
|
}
|
|
244
254
|
for (let { content } of patches) {
|
|
245
255
|
if (content) {
|
|
246
256
|
if (!Buffer.isBuffer(content)) {
|
|
247
257
|
content = Buffer.from(Object.values(content))
|
|
248
258
|
}
|
|
249
|
-
const syncd =
|
|
259
|
+
const syncd = proto.SyncdPatch.decode(content)
|
|
250
260
|
if (!syncd.version) {
|
|
251
261
|
syncd.version = { version: +collectionNode.attrs.version + 1 }
|
|
252
262
|
}
|
|
@@ -259,7 +269,7 @@ const extractSyncdPatches = async (result, options) => {
|
|
|
259
269
|
}
|
|
260
270
|
|
|
261
271
|
const downloadExternalBlob = async (blob, options) => {
|
|
262
|
-
const stream = await
|
|
272
|
+
const stream = await downloadContentFromMessage(blob, 'md-app-state', { options })
|
|
263
273
|
const bufferArray = []
|
|
264
274
|
for await (const chunk of stream) {
|
|
265
275
|
bufferArray.push(chunk)
|
|
@@ -269,13 +279,13 @@ const downloadExternalBlob = async (blob, options) => {
|
|
|
269
279
|
|
|
270
280
|
const downloadExternalPatch = async (blob, options) => {
|
|
271
281
|
const buffer = await downloadExternalBlob(blob, options)
|
|
272
|
-
const syncData =
|
|
282
|
+
const syncData = proto.SyncdMutations.decode(buffer)
|
|
273
283
|
return syncData
|
|
274
284
|
}
|
|
275
285
|
|
|
276
286
|
const decodeSyncdSnapshot = async (name, snapshot, getAppStateSyncKey, minimumVersionNumber, validateMacs = true) => {
|
|
277
287
|
const newState = newLTHashState()
|
|
278
|
-
newState.version =
|
|
288
|
+
newState.version = toNumber(snapshot.version.version)
|
|
279
289
|
const mutationMap = {}
|
|
280
290
|
const areMutationsRequired = typeof minimumVersionNumber === 'undefined'
|
|
281
291
|
|| newState.version > minimumVersionNumber
|
|
@@ -291,12 +301,12 @@ const decodeSyncdSnapshot = async (name, snapshot, getAppStateSyncKey, minimumVe
|
|
|
291
301
|
const base64Key = Buffer.from(snapshot.keyId.id).toString('base64')
|
|
292
302
|
const keyEnc = await getAppStateSyncKey(base64Key)
|
|
293
303
|
if (!keyEnc) {
|
|
294
|
-
throw new
|
|
304
|
+
throw new Boom(`failed to find key "${base64Key}" to decode mutation`)
|
|
295
305
|
}
|
|
296
306
|
const result = await mutationKeys(keyEnc.keyData)
|
|
297
307
|
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
|
298
308
|
if (Buffer.compare(snapshot.mac, computedSnapshotMac) !== 0) {
|
|
299
|
-
throw new
|
|
309
|
+
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name} from snapshot`)
|
|
300
310
|
}
|
|
301
311
|
}
|
|
302
312
|
return {
|
|
@@ -319,7 +329,7 @@ const decodePatches = async (name, syncds, initial, getAppStateSyncKey, options,
|
|
|
319
329
|
logger?.debug({ name, version, mutations: ref.mutations.length }, 'downloaded external patch')
|
|
320
330
|
syncd.mutations?.push(...ref.mutations)
|
|
321
331
|
}
|
|
322
|
-
const patchVersion =
|
|
332
|
+
const patchVersion = toNumber(version.version)
|
|
323
333
|
newState.version = patchVersion
|
|
324
334
|
const shouldMutate = typeof minimumVersionNumber === 'undefined' || patchVersion > minimumVersionNumber
|
|
325
335
|
const decodeResult = await decodeSyncdPatch(syncd, name, newState, getAppStateSyncKey, shouldMutate
|
|
@@ -335,12 +345,12 @@ const decodePatches = async (name, syncds, initial, getAppStateSyncKey, options,
|
|
|
335
345
|
const base64Key = Buffer.from(keyId.id).toString('base64')
|
|
336
346
|
const keyEnc = await getAppStateSyncKey(base64Key)
|
|
337
347
|
if (!keyEnc) {
|
|
338
|
-
throw new
|
|
348
|
+
throw new Boom(`failed to find key "${base64Key}" to decode mutation`)
|
|
339
349
|
}
|
|
340
350
|
const result = await mutationKeys(keyEnc.keyData)
|
|
341
351
|
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
|
342
352
|
if (Buffer.compare(snapshotMac, computedSnapshotMac) !== 0) {
|
|
343
|
-
throw new
|
|
353
|
+
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name}`)
|
|
344
354
|
}
|
|
345
355
|
}
|
|
346
356
|
// clear memory used up by the mutations
|
|
@@ -350,7 +360,7 @@ const decodePatches = async (name, syncds, initial, getAppStateSyncKey, options,
|
|
|
350
360
|
}
|
|
351
361
|
|
|
352
362
|
const chatModificationToAppPatch = (mod, jid) => {
|
|
353
|
-
const OP =
|
|
363
|
+
const OP = proto.SyncdMutation.SyncdOperation
|
|
354
364
|
const getMessageRange = (lastMessages) => {
|
|
355
365
|
let messageRange
|
|
356
366
|
if (Array.isArray(lastMessages)) {
|
|
@@ -359,16 +369,16 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
359
369
|
lastMessageTimestamp: lastMsg?.messageTimestamp,
|
|
360
370
|
messages: lastMessages?.length ? lastMessages.map(m => {
|
|
361
371
|
if (!((m.key?.id) || (m.key?.remoteJid))) {
|
|
362
|
-
throw new
|
|
372
|
+
throw new Boom('Incomplete key', { statusCode: 400, data: m })
|
|
363
373
|
}
|
|
364
|
-
if (
|
|
365
|
-
throw new
|
|
374
|
+
if (isJidGroup(m.key.remoteJid) && !m.key.fromMe && !m.key.participant) {
|
|
375
|
+
throw new Boom('Expected not from me message to have participant', { statusCode: 400, data: m })
|
|
366
376
|
}
|
|
367
|
-
if (!m.messageTimestamp || !
|
|
368
|
-
throw new
|
|
377
|
+
if (!m.messageTimestamp || !toNumber(m.messageTimestamp)) {
|
|
378
|
+
throw new Boom('Missing timestamp in last message list', { statusCode: 400, data: m })
|
|
369
379
|
}
|
|
370
380
|
if (m.key.participant) {
|
|
371
|
-
m.key.participant =
|
|
381
|
+
m.key.participant = jidNormalizedUser(m.key.participant)
|
|
372
382
|
}
|
|
373
383
|
return m
|
|
374
384
|
}) : undefined
|
|
@@ -522,7 +532,7 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
522
532
|
index: ['setting_pushName'],
|
|
523
533
|
type: 'critical_block',
|
|
524
534
|
apiVersion: 1,
|
|
525
|
-
operation: OP.SET
|
|
535
|
+
operation: OP.SET
|
|
526
536
|
}
|
|
527
537
|
}
|
|
528
538
|
else if ('quickReply' in mod) {
|
|
@@ -555,7 +565,7 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
555
565
|
index: ['label_edit', mod.addLabel.id],
|
|
556
566
|
type: 'regular',
|
|
557
567
|
apiVersion: 3,
|
|
558
|
-
operation: OP.SET
|
|
568
|
+
operation: OP.SET
|
|
559
569
|
}
|
|
560
570
|
}
|
|
561
571
|
else if ('addChatLabel' in mod) {
|
|
@@ -565,10 +575,10 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
565
575
|
labeled: true,
|
|
566
576
|
}
|
|
567
577
|
},
|
|
568
|
-
index: [
|
|
578
|
+
index: [LabelAssociationType.Chat, mod.addChatLabel.labelId, jid],
|
|
569
579
|
type: 'regular',
|
|
570
580
|
apiVersion: 3,
|
|
571
|
-
operation: OP.SET
|
|
581
|
+
operation: OP.SET
|
|
572
582
|
}
|
|
573
583
|
}
|
|
574
584
|
else if ('removeChatLabel' in mod) {
|
|
@@ -578,10 +588,10 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
578
588
|
labeled: false,
|
|
579
589
|
}
|
|
580
590
|
},
|
|
581
|
-
index: [
|
|
591
|
+
index: [LabelAssociationType.Chat, mod.removeChatLabel.labelId, jid],
|
|
582
592
|
type: 'regular',
|
|
583
593
|
apiVersion: 3,
|
|
584
|
-
operation: OP.SET
|
|
594
|
+
operation: OP.SET
|
|
585
595
|
}
|
|
586
596
|
}
|
|
587
597
|
else if ('addMessageLabel' in mod) {
|
|
@@ -592,7 +602,7 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
592
602
|
}
|
|
593
603
|
},
|
|
594
604
|
index: [
|
|
595
|
-
|
|
605
|
+
LabelAssociationType.Message,
|
|
596
606
|
mod.addMessageLabel.labelId,
|
|
597
607
|
jid,
|
|
598
608
|
mod.addMessageLabel.messageId,
|
|
@@ -601,7 +611,7 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
601
611
|
],
|
|
602
612
|
type: 'regular',
|
|
603
613
|
apiVersion: 3,
|
|
604
|
-
operation: OP.SET
|
|
614
|
+
operation: OP.SET
|
|
605
615
|
}
|
|
606
616
|
}
|
|
607
617
|
else if ('removeMessageLabel' in mod) {
|
|
@@ -612,7 +622,7 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
612
622
|
}
|
|
613
623
|
},
|
|
614
624
|
index: [
|
|
615
|
-
|
|
625
|
+
LabelAssociationType.Message,
|
|
616
626
|
mod.removeMessageLabel.labelId,
|
|
617
627
|
jid,
|
|
618
628
|
mod.removeMessageLabel.messageId,
|
|
@@ -621,11 +631,11 @@ const chatModificationToAppPatch = (mod, jid) => {
|
|
|
621
631
|
],
|
|
622
632
|
type: 'regular',
|
|
623
633
|
apiVersion: 3,
|
|
624
|
-
operation: OP.SET
|
|
634
|
+
operation: OP.SET
|
|
625
635
|
}
|
|
626
636
|
}
|
|
627
637
|
else {
|
|
628
|
-
throw new
|
|
638
|
+
throw new Boom('not supported')
|
|
629
639
|
}
|
|
630
640
|
patch.syncAction.timestamp = Date.now()
|
|
631
641
|
return patch
|
|
@@ -641,7 +651,7 @@ const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
|
641
651
|
{
|
|
642
652
|
id,
|
|
643
653
|
muteEndTime: action.muteAction?.muted
|
|
644
|
-
?
|
|
654
|
+
? toNumber(action.muteAction.muteEndTimestamp)
|
|
645
655
|
: null,
|
|
646
656
|
conditional: getChatUpdateConditional(id, undefined)
|
|
647
657
|
}
|
|
@@ -715,7 +725,7 @@ const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
|
715
725
|
else if (action?.pinAction) {
|
|
716
726
|
ev.emit('chats.update', [{
|
|
717
727
|
id,
|
|
718
|
-
pinned: action.pinAction?.pinned ?
|
|
728
|
+
pinned: action.pinAction?.pinned ? toNumber(action.timestamp) : null,
|
|
719
729
|
conditional: getChatUpdateConditional(id, undefined)
|
|
720
730
|
}])
|
|
721
731
|
}
|
|
@@ -759,14 +769,14 @@ const processSyncAction = (syncAction, ev, me, initialSyncOpts, logger) => {
|
|
|
759
769
|
type: action.labelAssociationAction.labeled
|
|
760
770
|
? 'add'
|
|
761
771
|
: 'remove',
|
|
762
|
-
association: type ===
|
|
772
|
+
association: type === LabelAssociationType.Chat
|
|
763
773
|
? {
|
|
764
|
-
type:
|
|
774
|
+
type: LabelAssociationType.Chat,
|
|
765
775
|
chatId: syncAction.index[2],
|
|
766
776
|
labelId: syncAction.index[1]
|
|
767
777
|
}
|
|
768
778
|
: {
|
|
769
|
-
type:
|
|
779
|
+
type: LabelAssociationType.Message,
|
|
770
780
|
chatId: syncAction.index[2],
|
|
771
781
|
messageId: syncAction.index[3],
|
|
772
782
|
labelId: syncAction.index[1]
|