@pontalabs/baileys 1.0.6 → 1.0.7
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 +42 -86
- package/engine-requirements.js +0 -10
package/lib/Socket/chats.js
CHANGED
|
@@ -1,87 +1,80 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
45
|
-
let historySyncPausedTimeout;
|
|
46
|
-
// Collections blocked on missing app state sync keys (mirrors WA Web's "Blocked" state).
|
|
47
|
-
// When a key arrives via APP_STATE_SYNC_KEY_SHARE, these are re-synced.
|
|
48
|
-
const blockedCollections = new Set();
|
|
49
|
-
const placeholderResendCache = config.placeholderResendCache ||
|
|
50
|
-
new NodeCache({
|
|
51
|
-
stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
52
|
-
useClones: false
|
|
53
|
-
});
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod }
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true })
|
|
8
|
+
|
|
9
|
+
const node_cache_1 = __importDefault(require("@cacheable/node-cache"))
|
|
10
|
+
const boom_1 = require("@hapi/boom")
|
|
11
|
+
const WAProto_1 = require("../../WAProto")
|
|
12
|
+
const Defaults_1 = require("../Defaults")
|
|
13
|
+
const Types_1 = require("../Types")
|
|
14
|
+
const Utils_1 = require("../Utils")
|
|
15
|
+
const make_mutex_1 = require("../Utils/make-mutex")
|
|
16
|
+
const WABinary_1 = require("../WABinary")
|
|
17
|
+
const WAUSync_1 = require("../WAUSync")
|
|
18
|
+
const socket_1 = require("./socket")
|
|
19
|
+
const MAX_SYNC_ATTEMPTS = 2
|
|
20
|
+
|
|
21
|
+
const makeChatsSocket = (config) => {
|
|
22
|
+
const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, } = config
|
|
23
|
+
const sock = socket_1.makeSocket(config)
|
|
24
|
+
const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, groupFetchAllParticipating } = sock
|
|
25
|
+
|
|
26
|
+
let privacySettings
|
|
27
|
+
let syncState = Types_1.SyncState.Connecting
|
|
28
|
+
|
|
29
|
+
/** this mutex ensures that the notifications (receipts, messages etc.) are processed in order */
|
|
30
|
+
const processingMutex = make_mutex_1.makeMutex()
|
|
31
|
+
|
|
32
|
+
// Timeout for AwaitingInitialSync State
|
|
33
|
+
let awaitingSyncTimeout
|
|
34
|
+
|
|
35
|
+
const placeholderResendCache = config.placeholderResendCache || new node_cache_1.default({
|
|
36
|
+
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY,
|
|
37
|
+
useClones: false
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
if (!config.placeholderResendCache) {
|
|
41
|
+
config.placeholderResendCache = placeholderResendCache
|
|
42
|
+
}
|
|
43
|
+
|
|
54
44
|
/** helper function to fetch the given app state sync key */
|
|
55
45
|
const getAppStateSyncKey = async (keyId) => {
|
|
56
|
-
const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId])
|
|
57
|
-
return key
|
|
58
|
-
}
|
|
46
|
+
const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId])
|
|
47
|
+
return key
|
|
48
|
+
}
|
|
49
|
+
|
|
59
50
|
const fetchPrivacySettings = async (force = false) => {
|
|
60
51
|
if (!privacySettings || force) {
|
|
61
52
|
const { content } = await query({
|
|
62
53
|
tag: 'iq',
|
|
63
54
|
attrs: {
|
|
64
55
|
xmlns: 'privacy',
|
|
65
|
-
to: S_WHATSAPP_NET,
|
|
56
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
66
57
|
type: 'get'
|
|
67
58
|
},
|
|
68
|
-
content: [
|
|
69
|
-
|
|
70
|
-
|
|
59
|
+
content: [
|
|
60
|
+
{ tag: 'privacy', attrs: {} }
|
|
61
|
+
]
|
|
62
|
+
})
|
|
63
|
+
privacySettings = WABinary_1.reduceBinaryNodeToDictionary(content?.[0], 'category')
|
|
71
64
|
}
|
|
72
|
-
return privacySettings
|
|
73
|
-
}
|
|
65
|
+
return privacySettings
|
|
66
|
+
}
|
|
67
|
+
|
|
74
68
|
/** helper function to run a privacy IQ query */
|
|
75
69
|
const privacyQuery = async (name, value) => {
|
|
76
70
|
await query({
|
|
77
71
|
tag: 'iq',
|
|
78
72
|
attrs: {
|
|
79
73
|
xmlns: 'privacy',
|
|
80
|
-
to: S_WHATSAPP_NET,
|
|
74
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
81
75
|
type: 'set'
|
|
82
76
|
},
|
|
83
|
-
content: [
|
|
84
|
-
{
|
|
77
|
+
content: [{
|
|
85
78
|
tag: 'privacy',
|
|
86
79
|
attrs: {},
|
|
87
80
|
content: [
|
|
@@ -90,123 +83,172 @@ export const makeChatsSocket = (config) => {
|
|
|
90
83
|
attrs: { name, value }
|
|
91
84
|
}
|
|
92
85
|
]
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
86
|
+
}]
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
97
90
|
const updateMessagesPrivacy = async (value) => {
|
|
98
|
-
await privacyQuery('messages', value)
|
|
99
|
-
}
|
|
91
|
+
await privacyQuery('messages', value)
|
|
92
|
+
}
|
|
93
|
+
|
|
100
94
|
const updateCallPrivacy = async (value) => {
|
|
101
|
-
await privacyQuery('calladd', value)
|
|
102
|
-
}
|
|
95
|
+
await privacyQuery('calladd', value)
|
|
96
|
+
}
|
|
97
|
+
|
|
103
98
|
const updateLastSeenPrivacy = async (value) => {
|
|
104
|
-
await privacyQuery('last', value)
|
|
105
|
-
}
|
|
99
|
+
await privacyQuery('last', value)
|
|
100
|
+
}
|
|
101
|
+
|
|
106
102
|
const updateOnlinePrivacy = async (value) => {
|
|
107
|
-
await privacyQuery('online', value)
|
|
108
|
-
}
|
|
103
|
+
await privacyQuery('online', value)
|
|
104
|
+
}
|
|
105
|
+
|
|
109
106
|
const updateProfilePicturePrivacy = async (value) => {
|
|
110
|
-
await privacyQuery('profile', value)
|
|
111
|
-
}
|
|
107
|
+
await privacyQuery('profile', value)
|
|
108
|
+
}
|
|
109
|
+
|
|
112
110
|
const updateStatusPrivacy = async (value) => {
|
|
113
|
-
await privacyQuery('status', value)
|
|
114
|
-
}
|
|
111
|
+
await privacyQuery('status', value)
|
|
112
|
+
}
|
|
113
|
+
|
|
115
114
|
const updateReadReceiptsPrivacy = async (value) => {
|
|
116
|
-
await privacyQuery('readreceipts', value)
|
|
117
|
-
}
|
|
115
|
+
await privacyQuery('readreceipts', value)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
118
|
const updateGroupsAddPrivacy = async (value) => {
|
|
119
|
-
await privacyQuery('groupadd', value)
|
|
120
|
-
}
|
|
119
|
+
await privacyQuery('groupadd', value)
|
|
120
|
+
}
|
|
121
|
+
|
|
121
122
|
const updateDefaultDisappearingMode = async (duration) => {
|
|
122
123
|
await query({
|
|
123
124
|
tag: 'iq',
|
|
124
125
|
attrs: {
|
|
125
126
|
xmlns: 'disappearing_mode',
|
|
126
|
-
to: S_WHATSAPP_NET,
|
|
127
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
127
128
|
type: 'set'
|
|
128
129
|
},
|
|
129
|
-
content: [
|
|
130
|
-
{
|
|
130
|
+
content: [{
|
|
131
131
|
tag: 'disappearing_mode',
|
|
132
132
|
attrs: {
|
|
133
133
|
duration: duration.toString()
|
|
134
134
|
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
}]
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
139
|
const getBotListV2 = async () => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
140
|
+
const resp = await query({
|
|
141
|
+
tag: 'iq',
|
|
142
|
+
attrs: {
|
|
143
|
+
xmlns: 'bot',
|
|
144
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
145
|
+
type: 'get'
|
|
146
|
+
},
|
|
147
|
+
content: [{
|
|
148
|
+
tag: 'bot',
|
|
149
|
+
attrs: {
|
|
150
|
+
v: '2'
|
|
151
|
+
}
|
|
152
|
+
}]
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
const botNode = WABinary_1.getBinaryNodeChild(resp, 'bot')
|
|
156
|
+
|
|
157
|
+
const botList = []
|
|
158
|
+
|
|
159
|
+
for(const section of WABinary_1.getBinaryNodeChildren(botNode, 'section')) {
|
|
160
|
+
if(section.attrs.type === 'all') {
|
|
161
|
+
for(const bot of WABinary_1.getBinaryNodeChildren(section, 'bot')) {
|
|
162
|
+
botList.push({
|
|
163
|
+
jid: bot.attrs.jid,
|
|
164
|
+
personaId: bot.attrs['persona_id']
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return botList
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const getLidUser = async (jid) => {
|
|
173
|
+
if (!jid) {
|
|
174
|
+
throw new boom_1.Boom('Please input a jid user')
|
|
167
175
|
}
|
|
168
|
-
|
|
169
|
-
|
|
176
|
+
|
|
177
|
+
if (!WABinary_1.isJidUser(jid)) {
|
|
178
|
+
throw new boom_1.Boom('Invalid JID: Not a user JID!')
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const targetJid = WABinary_1.jidNormalizedUser(jid)
|
|
182
|
+
|
|
183
|
+
const usyncQuery = new WAUSync_1.USyncQuery()
|
|
184
|
+
usyncQuery.protocols.push({
|
|
185
|
+
name: 'lid',
|
|
186
|
+
getQueryElement: () => ({
|
|
187
|
+
tag: 'lid',
|
|
188
|
+
attrs: {},
|
|
189
|
+
content: undefined
|
|
190
|
+
}),
|
|
191
|
+
getUserElement: () => null,
|
|
192
|
+
parser: (node) => node.attrs.val
|
|
193
|
+
})
|
|
194
|
+
usyncQuery.users.push({
|
|
195
|
+
id: targetJid
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
const result = await sock.executeUSyncQuery(usyncQuery)
|
|
199
|
+
|
|
200
|
+
if (result) {
|
|
201
|
+
return result.list
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
170
205
|
const fetchStatus = async (...jids) => {
|
|
171
|
-
const usyncQuery = new USyncQuery().withStatusProtocol()
|
|
206
|
+
const usyncQuery = new WAUSync_1.USyncQuery().withStatusProtocol()
|
|
207
|
+
|
|
172
208
|
for (const jid of jids) {
|
|
173
|
-
usyncQuery.withUser(new USyncUser().withId(jid))
|
|
209
|
+
usyncQuery.withUser(new WAUSync_1.USyncUser().withId(jid))
|
|
174
210
|
}
|
|
175
|
-
|
|
211
|
+
|
|
212
|
+
const result = await sock.executeUSyncQuery(usyncQuery)
|
|
213
|
+
|
|
176
214
|
if (result) {
|
|
177
|
-
return result.list
|
|
215
|
+
return result.list
|
|
178
216
|
}
|
|
179
|
-
}
|
|
180
|
-
const fetchDisappearingDuration = async (...jids) => {
|
|
181
|
-
const usyncQuery = new USyncQuery().withDisappearingModeProtocol()
|
|
217
|
+
}
|
|
218
|
+
const fetchDisappearingDuration = async (...jids) => {
|
|
219
|
+
const usyncQuery = new WAUSync_1.USyncQuery().withDisappearingModeProtocol()
|
|
220
|
+
|
|
182
221
|
for (const jid of jids) {
|
|
183
|
-
usyncQuery.withUser(new USyncUser().withId(jid))
|
|
222
|
+
usyncQuery.withUser(new WAUSync_1.USyncUser().withId(jid))
|
|
184
223
|
}
|
|
185
|
-
|
|
224
|
+
|
|
225
|
+
const result = await sock.executeUSyncQuery(usyncQuery)
|
|
186
226
|
if (result) {
|
|
187
|
-
return result.list
|
|
227
|
+
return result.list
|
|
188
228
|
}
|
|
189
|
-
}
|
|
229
|
+
}
|
|
230
|
+
|
|
190
231
|
/** update the profile picture for yourself or a group */
|
|
191
|
-
const updateProfilePicture = async (jid, content
|
|
192
|
-
let targetJid
|
|
232
|
+
const updateProfilePicture = async (jid, content) => {
|
|
233
|
+
let targetJid
|
|
234
|
+
|
|
193
235
|
if (!jid) {
|
|
194
|
-
throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update')
|
|
195
|
-
}
|
|
196
|
-
if (jidNormalizedUser(jid) !== jidNormalizedUser(authState.creds.me.id)) {
|
|
197
|
-
targetJid = jidNormalizedUser(jid); // in case it is someone other than us
|
|
236
|
+
throw new boom_1.Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update')
|
|
198
237
|
}
|
|
199
|
-
|
|
200
|
-
|
|
238
|
+
|
|
239
|
+
if (WABinary_1.jidNormalizedUser(jid) !== WABinary_1.jidNormalizedUser(authState.creds.me.id)) {
|
|
240
|
+
targetJid = WABinary_1.jidNormalizedUser(jid) // in case it is someone other than us
|
|
201
241
|
}
|
|
202
|
-
|
|
242
|
+
|
|
243
|
+
const { img } = await Utils_1.generateProfilePicture(content)
|
|
244
|
+
|
|
203
245
|
await query({
|
|
204
246
|
tag: 'iq',
|
|
205
247
|
attrs: {
|
|
206
|
-
|
|
248
|
+
target: targetJid,
|
|
249
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
207
250
|
type: 'set',
|
|
208
|
-
xmlns: 'w:profile:picture'
|
|
209
|
-
...(targetJid ? { target: targetJid } : {})
|
|
251
|
+
xmlns: 'w:profile:picture'
|
|
210
252
|
},
|
|
211
253
|
content: [
|
|
212
254
|
{
|
|
@@ -215,36 +257,38 @@ export const makeChatsSocket = (config) => {
|
|
|
215
257
|
content: img
|
|
216
258
|
}
|
|
217
259
|
]
|
|
218
|
-
})
|
|
219
|
-
}
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
|
|
220
263
|
/** remove the profile picture for yourself or a group */
|
|
221
264
|
const removeProfilePicture = async (jid) => {
|
|
222
|
-
let targetJid
|
|
265
|
+
let targetJid
|
|
266
|
+
|
|
223
267
|
if (!jid) {
|
|
224
|
-
throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update')
|
|
268
|
+
throw new boom_1.Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update')
|
|
225
269
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
else {
|
|
230
|
-
targetJid = undefined;
|
|
270
|
+
|
|
271
|
+
if (WABinary_1.jidNormalizedUser(jid) !== WABinary_1.jidNormalizedUser(authState.creds.me.id)) {
|
|
272
|
+
targetJid = WABinary_1.jidNormalizedUser(jid) // in case it is someone other than us
|
|
231
273
|
}
|
|
274
|
+
|
|
232
275
|
await query({
|
|
233
276
|
tag: 'iq',
|
|
234
277
|
attrs: {
|
|
235
|
-
|
|
278
|
+
target: targetJid,
|
|
279
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
236
280
|
type: 'set',
|
|
237
|
-
xmlns: 'w:profile:picture'
|
|
238
|
-
...(targetJid ? { target: targetJid } : {})
|
|
281
|
+
xmlns: 'w:profile:picture'
|
|
239
282
|
}
|
|
240
|
-
})
|
|
241
|
-
}
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
|
|
242
286
|
/** update the profile status for yourself */
|
|
243
287
|
const updateProfileStatus = async (status) => {
|
|
244
288
|
await query({
|
|
245
289
|
tag: 'iq',
|
|
246
290
|
attrs: {
|
|
247
|
-
to: S_WHATSAPP_NET,
|
|
291
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
248
292
|
type: 'set',
|
|
249
293
|
xmlns: 'status'
|
|
250
294
|
},
|
|
@@ -255,75 +299,48 @@ export const makeChatsSocket = (config) => {
|
|
|
255
299
|
content: Buffer.from(status, 'utf-8')
|
|
256
300
|
}
|
|
257
301
|
]
|
|
258
|
-
})
|
|
259
|
-
}
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
|
|
260
305
|
const updateProfileName = async (name) => {
|
|
261
|
-
await chatModify({ pushNameSetting: name }, '')
|
|
262
|
-
}
|
|
306
|
+
await chatModify({ pushNameSetting: name }, '')
|
|
307
|
+
}
|
|
308
|
+
|
|
263
309
|
const fetchBlocklist = async () => {
|
|
264
310
|
const result = await query({
|
|
265
311
|
tag: 'iq',
|
|
266
312
|
attrs: {
|
|
267
313
|
xmlns: 'blocklist',
|
|
268
|
-
to: S_WHATSAPP_NET,
|
|
314
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
269
315
|
type: 'get'
|
|
270
316
|
}
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
const listNode = WABinary_1.getBinaryNodeChild(result, 'list')
|
|
320
|
+
|
|
321
|
+
return WABinary_1.getBinaryNodeChildren(listNode, 'item').map((n) => n.attrs.jid)
|
|
322
|
+
}
|
|
323
|
+
|
|
275
324
|
const updateBlockStatus = async (jid, action) => {
|
|
276
|
-
const normalizedJid = jidNormalizedUser(jid);
|
|
277
|
-
let lid;
|
|
278
|
-
let pn_jid;
|
|
279
|
-
if (isLidUser(normalizedJid) || isHostedLidUser(normalizedJid)) {
|
|
280
|
-
lid = normalizedJid;
|
|
281
|
-
if (action === 'block') {
|
|
282
|
-
const pn = await signalRepository.lidMapping.getPNForLID(normalizedJid);
|
|
283
|
-
if (!pn) {
|
|
284
|
-
throw new Boom(`Unable to resolve PN JID for LID: ${jid}`, { statusCode: 400 });
|
|
285
|
-
}
|
|
286
|
-
pn_jid = jidNormalizedUser(pn);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
else if (isPnUser(normalizedJid) || isHostedPnUser(normalizedJid)) {
|
|
290
|
-
const mapped = await signalRepository.lidMapping.getLIDForPN(normalizedJid);
|
|
291
|
-
if (!mapped) {
|
|
292
|
-
throw new Boom(`Unable to resolve LID for PN JID: ${jid}`, { statusCode: 400 });
|
|
293
|
-
}
|
|
294
|
-
lid = mapped;
|
|
295
|
-
if (action === 'block') {
|
|
296
|
-
pn_jid = jidNormalizedUser(normalizedJid);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
throw new Boom(`Invalid jid: ${jid}`, { statusCode: 400 });
|
|
301
|
-
}
|
|
302
|
-
const itemAttrs = {
|
|
303
|
-
action,
|
|
304
|
-
jid: lid
|
|
305
|
-
};
|
|
306
|
-
if (action === 'block') {
|
|
307
|
-
if (!pn_jid) {
|
|
308
|
-
throw new Boom(`pn_jid required for block: ${jid}`, { statusCode: 400 });
|
|
309
|
-
}
|
|
310
|
-
itemAttrs.pn_jid = pn_jid;
|
|
311
|
-
}
|
|
312
325
|
await query({
|
|
313
326
|
tag: 'iq',
|
|
314
327
|
attrs: {
|
|
315
328
|
xmlns: 'blocklist',
|
|
316
|
-
to: S_WHATSAPP_NET,
|
|
329
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
317
330
|
type: 'set'
|
|
318
331
|
},
|
|
319
332
|
content: [
|
|
320
333
|
{
|
|
321
334
|
tag: 'item',
|
|
322
|
-
attrs:
|
|
335
|
+
attrs: {
|
|
336
|
+
action,
|
|
337
|
+
jid
|
|
338
|
+
}
|
|
323
339
|
}
|
|
324
340
|
]
|
|
325
|
-
})
|
|
326
|
-
}
|
|
341
|
+
})
|
|
342
|
+
}
|
|
343
|
+
|
|
327
344
|
const getBusinessProfile = async (jid) => {
|
|
328
345
|
const results = await query({
|
|
329
346
|
tag: 'iq',
|
|
@@ -332,133 +349,121 @@ export const makeChatsSocket = (config) => {
|
|
|
332
349
|
xmlns: 'w:biz',
|
|
333
350
|
type: 'get'
|
|
334
351
|
},
|
|
335
|
-
content: [
|
|
336
|
-
{
|
|
352
|
+
content: [{
|
|
337
353
|
tag: 'business_profile',
|
|
338
354
|
attrs: { v: '244' },
|
|
339
|
-
content: [
|
|
340
|
-
{
|
|
355
|
+
content: [{
|
|
341
356
|
tag: 'profile',
|
|
342
357
|
attrs: { jid }
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const profiles = getBinaryNodeChild(profileNode, 'profile')
|
|
358
|
+
}]
|
|
359
|
+
}]
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
const profileNode = WABinary_1.getBinaryNodeChild(results, 'business_profile')
|
|
363
|
+
|
|
364
|
+
const profiles = WABinary_1.getBinaryNodeChild(profileNode, 'profile')
|
|
365
|
+
|
|
350
366
|
if (profiles) {
|
|
351
|
-
const address = getBinaryNodeChild(profiles, 'address')
|
|
352
|
-
const description = getBinaryNodeChild(profiles, 'description')
|
|
353
|
-
const website = getBinaryNodeChild(profiles, 'website')
|
|
354
|
-
const email = getBinaryNodeChild(profiles, 'email')
|
|
355
|
-
const category = getBinaryNodeChild(getBinaryNodeChild(profiles, 'categories'), 'category')
|
|
356
|
-
const businessHours = getBinaryNodeChild(profiles, 'business_hours')
|
|
367
|
+
const address = WABinary_1.getBinaryNodeChild(profiles, 'address')
|
|
368
|
+
const description = WABinary_1.getBinaryNodeChild(profiles, 'description')
|
|
369
|
+
const website = WABinary_1.getBinaryNodeChild(profiles, 'website')
|
|
370
|
+
const email = WABinary_1.getBinaryNodeChild(profiles, 'email')
|
|
371
|
+
const category = WABinary_1.getBinaryNodeChild(WABinary_1.getBinaryNodeChild(profiles, 'categories'), 'category')
|
|
372
|
+
const businessHours = WABinary_1.getBinaryNodeChild(profiles, 'business_hours')
|
|
357
373
|
const businessHoursConfig = businessHours
|
|
358
|
-
? getBinaryNodeChildren(businessHours, 'business_hours_config')
|
|
359
|
-
: undefined
|
|
360
|
-
const websiteStr = website?.content?.toString()
|
|
374
|
+
? WABinary_1.getBinaryNodeChildren(businessHours, 'business_hours_config')
|
|
375
|
+
: undefined
|
|
376
|
+
const websiteStr = website?.content?.toString()
|
|
377
|
+
|
|
361
378
|
return {
|
|
362
|
-
wid: profiles
|
|
379
|
+
wid: profiles?.attrs?.jid,
|
|
363
380
|
address: address?.content?.toString(),
|
|
364
381
|
description: description?.content?.toString() || '',
|
|
365
382
|
website: websiteStr ? [websiteStr] : [],
|
|
366
383
|
email: email?.content?.toString(),
|
|
367
384
|
category: category?.content?.toString(),
|
|
368
|
-
business_hours: {
|
|
385
|
+
'business_hours': {
|
|
369
386
|
timezone: businessHours?.attrs?.timezone,
|
|
370
|
-
business_config: businessHoursConfig?.map(({ attrs }) => attrs)
|
|
387
|
+
'business_config': businessHoursConfig?.map(({ attrs }) => attrs)
|
|
371
388
|
}
|
|
372
|
-
}
|
|
389
|
+
}
|
|
373
390
|
}
|
|
374
|
-
}
|
|
391
|
+
}
|
|
392
|
+
|
|
375
393
|
const cleanDirtyBits = async (type, fromTimestamp) => {
|
|
376
|
-
logger.info({ fromTimestamp }, 'clean dirty bits ' + type)
|
|
394
|
+
logger.info({ fromTimestamp }, 'clean dirty bits ' + type)
|
|
377
395
|
await sendNode({
|
|
378
396
|
tag: 'iq',
|
|
379
397
|
attrs: {
|
|
380
|
-
to: S_WHATSAPP_NET,
|
|
398
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
381
399
|
type: 'set',
|
|
382
400
|
xmlns: 'urn:xmpp:whatsapp:dirty',
|
|
383
|
-
id: generateMessageTag()
|
|
401
|
+
id: generateMessageTag(),
|
|
384
402
|
},
|
|
385
403
|
content: [
|
|
386
404
|
{
|
|
387
405
|
tag: 'clean',
|
|
388
406
|
attrs: {
|
|
389
407
|
type,
|
|
390
|
-
...(fromTimestamp ? { timestamp: fromTimestamp.toString() } : null)
|
|
408
|
+
...(fromTimestamp ? { timestamp: fromTimestamp.toString() } : null),
|
|
391
409
|
}
|
|
392
410
|
}
|
|
393
411
|
]
|
|
394
|
-
})
|
|
395
|
-
}
|
|
412
|
+
})
|
|
413
|
+
}
|
|
414
|
+
|
|
396
415
|
const newAppStateChunkHandler = (isInitialSync) => {
|
|
397
416
|
return {
|
|
398
417
|
onMutation(mutation) {
|
|
399
|
-
processSyncAction(mutation, ev, authState.creds.me, isInitialSync ? { accountSettings: authState.creds.accountSettings } : undefined, logger)
|
|
418
|
+
Utils_1.processSyncAction(mutation, ev, authState.creds.me, isInitialSync ? { accountSettings: authState.creds.accountSettings } : undefined, logger)
|
|
400
419
|
}
|
|
401
|
-
}
|
|
402
|
-
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
403
423
|
const resyncAppState = ev.createBufferedFunction(async (collections, isInitialSync) => {
|
|
404
|
-
const appStateSyncKeyCache = new Map();
|
|
405
|
-
const getCachedAppStateSyncKey = async (keyId) => {
|
|
406
|
-
if (appStateSyncKeyCache.has(keyId)) {
|
|
407
|
-
return appStateSyncKeyCache.get(keyId) ?? undefined;
|
|
408
|
-
}
|
|
409
|
-
const key = await getAppStateSyncKey(keyId);
|
|
410
|
-
appStateSyncKeyCache.set(keyId, key ?? null);
|
|
411
|
-
return key;
|
|
412
|
-
};
|
|
413
424
|
// we use this to determine which events to fire
|
|
414
425
|
// otherwise when we resync from scratch -- all notifications will fire
|
|
415
|
-
const initialVersionMap = {}
|
|
416
|
-
const globalMutationMap = {}
|
|
426
|
+
const initialVersionMap = {}
|
|
427
|
+
const globalMutationMap = {}
|
|
417
428
|
await authState.keys.transaction(async () => {
|
|
418
|
-
const collectionsToHandle = new Set(collections)
|
|
429
|
+
const collectionsToHandle = new Set(collections)
|
|
419
430
|
// in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
|
|
420
|
-
const attemptsMap = {}
|
|
421
|
-
// collections that failed and need a full snapshot on retry
|
|
422
|
-
// mirrors WA Web's ErrorFatal -> force snapshot behavior
|
|
423
|
-
const forceSnapshotCollections = new Set();
|
|
431
|
+
const attemptsMap = {}
|
|
424
432
|
// keep executing till all collections are done
|
|
425
433
|
// sometimes a single patch request will not return all the patches (God knows why)
|
|
426
434
|
// so we fetch till they're all done (this is determined by the "has_more_patches" flag)
|
|
427
435
|
while (collectionsToHandle.size) {
|
|
428
|
-
const states = {}
|
|
429
|
-
const nodes = []
|
|
436
|
+
const states = {}
|
|
437
|
+
const nodes = []
|
|
438
|
+
|
|
430
439
|
for (const name of collectionsToHandle) {
|
|
431
|
-
const result = await authState.keys.get('app-state-sync-version', [name])
|
|
432
|
-
let state = result[name]
|
|
440
|
+
const result = await authState.keys.get('app-state-sync-version', [name])
|
|
441
|
+
let state = result[name]
|
|
433
442
|
if (state) {
|
|
434
|
-
state = ensureLTHashStateVersion(state);
|
|
435
443
|
if (typeof initialVersionMap[name] === 'undefined') {
|
|
436
|
-
initialVersionMap[name] = state.version
|
|
444
|
+
initialVersionMap[name] = state.version
|
|
437
445
|
}
|
|
438
446
|
}
|
|
439
447
|
else {
|
|
440
|
-
state = newLTHashState()
|
|
441
|
-
}
|
|
442
|
-
states[name] = state;
|
|
443
|
-
const shouldForceSnapshot = forceSnapshotCollections.has(name);
|
|
444
|
-
if (shouldForceSnapshot) {
|
|
445
|
-
forceSnapshotCollections.delete(name);
|
|
448
|
+
state = Utils_1.newLTHashState()
|
|
446
449
|
}
|
|
447
|
-
|
|
450
|
+
states[name] = state
|
|
451
|
+
logger.info(`resyncing ${name} from v${state.version}`)
|
|
448
452
|
nodes.push({
|
|
449
453
|
tag: 'collection',
|
|
450
454
|
attrs: {
|
|
451
455
|
name,
|
|
452
456
|
version: state.version.toString(),
|
|
453
|
-
// return snapshot if
|
|
454
|
-
return_snapshot: (
|
|
457
|
+
// return snapshot if being synced from scratch
|
|
458
|
+
'return_snapshot': (!state.version).toString()
|
|
455
459
|
}
|
|
456
|
-
})
|
|
460
|
+
})
|
|
457
461
|
}
|
|
462
|
+
|
|
458
463
|
const result = await query({
|
|
459
464
|
tag: 'iq',
|
|
460
465
|
attrs: {
|
|
461
|
-
to: S_WHATSAPP_NET,
|
|
466
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
462
467
|
xmlns: 'w:sync:app:state',
|
|
463
468
|
type: 'set'
|
|
464
469
|
},
|
|
@@ -469,159 +474,125 @@ export const makeChatsSocket = (config) => {
|
|
|
469
474
|
content: nodes
|
|
470
475
|
}
|
|
471
476
|
]
|
|
472
|
-
})
|
|
477
|
+
})
|
|
478
|
+
|
|
473
479
|
// extract from binary node
|
|
474
|
-
const decoded = await extractSyncdPatches(result, config?.options)
|
|
480
|
+
const decoded = await Utils_1.extractSyncdPatches(result, config?.options)
|
|
481
|
+
|
|
475
482
|
for (const key in decoded) {
|
|
476
|
-
const name = key
|
|
477
|
-
const { patches, hasMorePatches, snapshot } = decoded[name]
|
|
483
|
+
const name = key
|
|
484
|
+
const { patches, hasMorePatches, snapshot } = decoded[name]
|
|
478
485
|
try {
|
|
479
486
|
if (snapshot) {
|
|
480
|
-
const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot,
|
|
481
|
-
states[name] = newState
|
|
482
|
-
Object.assign(globalMutationMap, mutationMap)
|
|
483
|
-
logger.info(`restored state of ${name} from snapshot to v${newState.version} with mutations`)
|
|
484
|
-
await authState.keys.set({ 'app-state-sync-version': { [name]: newState } })
|
|
487
|
+
const { state: newState, mutationMap } = await Utils_1.decodeSyncdSnapshot(name, snapshot, getAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot)
|
|
488
|
+
states[name] = newState
|
|
489
|
+
Object.assign(globalMutationMap, mutationMap)
|
|
490
|
+
logger.info(`restored state of ${name} from snapshot to v${newState.version} with mutations`)
|
|
491
|
+
await authState.keys.set({ 'app-state-sync-version': { [name]: newState } })
|
|
485
492
|
}
|
|
493
|
+
|
|
486
494
|
// only process if there are syncd patches
|
|
487
495
|
if (patches.length) {
|
|
488
|
-
const { state: newState, mutationMap } = await decodePatches(name, patches, states[name],
|
|
489
|
-
await authState.keys.set({ 'app-state-sync-version': { [name]: newState } })
|
|
490
|
-
logger.info(`synced ${name} to v${newState.version}`)
|
|
491
|
-
initialVersionMap[name] = newState.version
|
|
492
|
-
Object.assign(globalMutationMap, mutationMap)
|
|
496
|
+
const { state: newState, mutationMap } = await Utils_1.decodePatches(name, patches, states[name], getAppStateSyncKey, config.options, initialVersionMap[name], logger, appStateMacVerification.patch)
|
|
497
|
+
await authState.keys.set({ 'app-state-sync-version': { [name]: newState } })
|
|
498
|
+
logger.info(`synced ${name} to v${newState.version}`)
|
|
499
|
+
initialVersionMap[name] = newState.version
|
|
500
|
+
Object.assign(globalMutationMap, mutationMap)
|
|
493
501
|
}
|
|
502
|
+
|
|
494
503
|
if (hasMorePatches) {
|
|
495
|
-
logger.info(`${name} has more patches...`)
|
|
504
|
+
logger.info(`${name} has more patches...`)
|
|
505
|
+
}
|
|
506
|
+
else { // collection is done with sync
|
|
507
|
+
collectionsToHandle.delete(name)
|
|
496
508
|
}
|
|
497
|
-
|
|
498
|
-
// collection is done with sync
|
|
499
|
-
collectionsToHandle.delete(name);
|
|
500
|
-
}
|
|
501
|
-
}
|
|
509
|
+
}
|
|
502
510
|
catch (error) {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
//
|
|
515
|
-
|
|
516
|
-
blockedCollections.add(name);
|
|
517
|
-
collectionsToHandle.delete(name);
|
|
518
|
-
}
|
|
519
|
-
else if (isMissingKeyError(error)) {
|
|
520
|
-
// Retry with a snapshot which may use a different key.
|
|
521
|
-
logger.info(logData, `${name} blocked on missing key from v${states[name].version}, retrying with snapshot`);
|
|
522
|
-
forceSnapshotCollections.add(name);
|
|
523
|
-
}
|
|
524
|
-
else if (isAppStateSyncIrrecoverable(error, attemptsMap[name])) {
|
|
525
|
-
logger.warn(logData, `failed to sync ${name} from v${states[name].version}, giving up`);
|
|
526
|
-
collectionsToHandle.delete(name);
|
|
527
|
-
}
|
|
528
|
-
else {
|
|
529
|
-
logger.info(logData, `failed to sync ${name} from v${states[name].version}, forcing snapshot retry`);
|
|
530
|
-
// force a full snapshot on retry to recover from
|
|
531
|
-
// corrupted local state (e.g. LTHash MAC mismatch)
|
|
532
|
-
forceSnapshotCollections.add(name);
|
|
511
|
+
// if retry attempts overshoot
|
|
512
|
+
// or key not found
|
|
513
|
+
const isIrrecoverableError = attemptsMap[name] >= MAX_SYNC_ATTEMPTS
|
|
514
|
+
|| error.output?.statusCode === 404
|
|
515
|
+
|| error.name === 'TypeError'
|
|
516
|
+
logger.info({ name, error: error.stack }, `failed to sync state from version${isIrrecoverableError ? '' : ', removing and trying from scratch'}`)
|
|
517
|
+
await authState.keys.set({ 'app-state-sync-version': { [name]: null } })
|
|
518
|
+
// increment number of retries
|
|
519
|
+
attemptsMap[name] = (attemptsMap[name] || 0) + 1
|
|
520
|
+
|
|
521
|
+
if (isIrrecoverableError) {
|
|
522
|
+
// stop retrying
|
|
523
|
+
collectionsToHandle.delete(name)
|
|
533
524
|
}
|
|
534
525
|
}
|
|
535
526
|
}
|
|
536
527
|
}
|
|
537
|
-
}, authState?.creds?.me?.id || 'resync-app-state')
|
|
538
|
-
|
|
528
|
+
}, authState?.creds?.me?.id || 'resync-app-state')
|
|
529
|
+
|
|
530
|
+
const { onMutation } = newAppStateChunkHandler(isInitialSync)
|
|
531
|
+
|
|
539
532
|
for (const key in globalMutationMap) {
|
|
540
|
-
onMutation(globalMutationMap[key])
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
/**
|
|
544
|
-
* fetch the profile picture of a user/group
|
|
545
|
-
* type = "preview" for a low res picture
|
|
546
|
-
* type = "image for the high res picture"
|
|
547
|
-
*/
|
|
548
|
-
const profilePictureUrl = async (jid, type = 'preview', timeoutMs) => {
|
|
549
|
-
const baseContent = [{ tag: 'picture', attrs: { type, query: 'url' } }];
|
|
550
|
-
// WA Web only includes tctoken for user JIDs (not groups/newsletters)
|
|
551
|
-
// and never for own profile pic (Chat model for self has no tcToken).
|
|
552
|
-
// Including tctoken for own JID causes the server to never respond.
|
|
553
|
-
const normalizedJid = jidNormalizedUser(jid);
|
|
554
|
-
const isUserJid = isPnUser(normalizedJid) || isLidUser(normalizedJid);
|
|
555
|
-
const me = authState.creds.me;
|
|
556
|
-
const isSelf = me && (normalizedJid === jidNormalizedUser(me.id) || (me.lid && normalizedJid === jidNormalizedUser(me.lid)));
|
|
557
|
-
let content = baseContent;
|
|
558
|
-
if (serverProps.profilePicPrivacyToken && isUserJid && !isSelf) {
|
|
559
|
-
content = await buildTcTokenFromJid({
|
|
560
|
-
authState,
|
|
561
|
-
jid: normalizedJid,
|
|
562
|
-
baseContent,
|
|
563
|
-
getLIDForPN
|
|
564
|
-
});
|
|
533
|
+
onMutation(globalMutationMap[key])
|
|
565
534
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
attrs: {
|
|
570
|
-
target: jid,
|
|
571
|
-
to: S_WHATSAPP_NET,
|
|
572
|
-
type: 'get',
|
|
573
|
-
xmlns: 'w:profile:picture'
|
|
574
|
-
},
|
|
575
|
-
content
|
|
576
|
-
}, timeoutMs);
|
|
577
|
-
const child = getBinaryNodeChild(result, 'picture');
|
|
578
|
-
return child?.attrs?.url;
|
|
579
|
-
};
|
|
535
|
+
})
|
|
536
|
+
|
|
537
|
+
// source: https://github.com/WhiskeySockets/Baileys/pull/1677
|
|
580
538
|
const createCallLink = async (type, event, timeoutMs) => {
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
539
|
+
type = type?.toLowerCase()
|
|
540
|
+
|
|
541
|
+
if (!type || (type !== 'audio' && type !== 'video')) {
|
|
542
|
+
throw new Error('Make sure the type is audio or video!')
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const result = await query({
|
|
546
|
+
tag: 'call',
|
|
547
|
+
attrs: {
|
|
548
|
+
id: generateMessageTag(),
|
|
549
|
+
to: '@call'
|
|
550
|
+
},
|
|
551
|
+
content: [{
|
|
552
|
+
tag: 'link_create',
|
|
553
|
+
attrs: {
|
|
554
|
+
media: type
|
|
555
|
+
},
|
|
556
|
+
content: event ? [{
|
|
557
|
+
tag: 'event',
|
|
558
|
+
attrs: {
|
|
559
|
+
start_time: String(event)
|
|
560
|
+
}
|
|
561
|
+
}] : undefined
|
|
562
|
+
}]
|
|
563
|
+
}, timeoutMs)
|
|
564
|
+
|
|
565
|
+
const child = WABinary_1.getBinaryNodeChild(result, 'link_create')
|
|
566
|
+
const token = child?.attrs?.token
|
|
567
|
+
|
|
568
|
+
return type === 'audio' ? Defaults_1.CALL_AUDIO_PREFIX + token : Defaults_1.CALL_VIDEO_PREFIX + token
|
|
569
|
+
}
|
|
570
|
+
|
|
598
571
|
const sendPresenceUpdate = async (type, toJid) => {
|
|
599
|
-
const me = authState.creds.me
|
|
600
|
-
|
|
601
|
-
if (
|
|
572
|
+
const me = authState.creds.me
|
|
573
|
+
|
|
574
|
+
if (type === 'available' || type === 'unavailable') {
|
|
602
575
|
if (!me.name) {
|
|
603
|
-
logger.warn('no name present, ignoring presence update request...')
|
|
604
|
-
return
|
|
605
|
-
}
|
|
606
|
-
ev.emit('connection.update', { isOnline: isAvailableType });
|
|
607
|
-
if (isAvailableType) {
|
|
608
|
-
void sendUnifiedSession();
|
|
576
|
+
logger.warn('no name present, ignoring presence update request...')
|
|
577
|
+
return
|
|
609
578
|
}
|
|
579
|
+
|
|
580
|
+
ev.emit('connection.update', { isOnline: type === 'available' })
|
|
610
581
|
await sendNode({
|
|
611
582
|
tag: 'presence',
|
|
612
583
|
attrs: {
|
|
613
584
|
name: me.name.replace(/@/g, ''),
|
|
614
585
|
type
|
|
615
586
|
}
|
|
616
|
-
})
|
|
587
|
+
})
|
|
617
588
|
}
|
|
618
589
|
else {
|
|
619
|
-
|
|
620
|
-
|
|
590
|
+
const { server } = WABinary_1.jidDecode(toJid)
|
|
591
|
+
|
|
621
592
|
await sendNode({
|
|
622
593
|
tag: 'chatstate',
|
|
623
594
|
attrs: {
|
|
624
|
-
from:
|
|
595
|
+
from: server === 'lid' ? me.lid : me.id,
|
|
625
596
|
to: toJid
|
|
626
597
|
},
|
|
627
598
|
content: [
|
|
@@ -630,82 +601,96 @@ export const makeChatsSocket = (config) => {
|
|
|
630
601
|
attrs: type === 'recording' ? { media: 'audio' } : {}
|
|
631
602
|
}
|
|
632
603
|
]
|
|
633
|
-
})
|
|
604
|
+
})
|
|
634
605
|
}
|
|
635
|
-
}
|
|
606
|
+
}
|
|
607
|
+
|
|
636
608
|
/**
|
|
637
609
|
* @param toJid the jid to subscribe to
|
|
638
610
|
* @param tcToken token for subscription, use if present
|
|
639
611
|
*/
|
|
640
|
-
const presenceSubscribe =
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
}
|
|
612
|
+
const presenceSubscribe = (toJid, tcToken) => (sendNode({
|
|
613
|
+
tag: 'presence',
|
|
614
|
+
attrs: {
|
|
615
|
+
to: toJid,
|
|
616
|
+
id: generateMessageTag(),
|
|
617
|
+
type: 'subscribe'
|
|
618
|
+
},
|
|
619
|
+
content: tcToken
|
|
620
|
+
? [
|
|
621
|
+
{
|
|
622
|
+
tag: 'tctoken',
|
|
623
|
+
attrs: {},
|
|
624
|
+
content: tcToken
|
|
625
|
+
}
|
|
626
|
+
]
|
|
627
|
+
: undefined
|
|
628
|
+
}))
|
|
629
|
+
|
|
657
630
|
const handlePresenceUpdate = ({ tag, attrs, content }) => {
|
|
658
|
-
let presence
|
|
659
|
-
const jid = attrs.from
|
|
660
|
-
const participant = attrs.participant || attrs.from
|
|
661
|
-
|
|
662
|
-
|
|
631
|
+
let presence
|
|
632
|
+
const jid = attrs.from
|
|
633
|
+
const participant = attrs.participant || attrs.from
|
|
634
|
+
|
|
635
|
+
if (shouldIgnoreJid(jid) && jid !== '@s.whatsapp.net') {
|
|
636
|
+
return
|
|
663
637
|
}
|
|
638
|
+
|
|
664
639
|
if (tag === 'presence') {
|
|
665
640
|
presence = {
|
|
666
641
|
lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
|
|
667
|
-
lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
|
|
668
|
-
|
|
669
|
-
};
|
|
642
|
+
lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
|
|
643
|
+
}
|
|
670
644
|
}
|
|
645
|
+
|
|
671
646
|
else if (Array.isArray(content)) {
|
|
672
|
-
const [firstChild] = content
|
|
673
|
-
let type = firstChild.tag
|
|
647
|
+
const [firstChild] = content
|
|
648
|
+
let type = firstChild.tag
|
|
649
|
+
|
|
674
650
|
if (type === 'paused') {
|
|
675
|
-
type = 'available'
|
|
651
|
+
type = 'available'
|
|
676
652
|
}
|
|
653
|
+
|
|
677
654
|
if (firstChild.attrs?.media === 'audio') {
|
|
678
|
-
type = 'recording'
|
|
655
|
+
type = 'recording'
|
|
679
656
|
}
|
|
680
|
-
|
|
657
|
+
|
|
658
|
+
presence = { lastKnownPresence: type }
|
|
681
659
|
}
|
|
660
|
+
|
|
682
661
|
else {
|
|
683
|
-
logger.error({ tag, attrs, content }, 'recv invalid presence node')
|
|
662
|
+
logger.error({ tag, attrs, content }, 'recv invalid presence node')
|
|
684
663
|
}
|
|
664
|
+
|
|
685
665
|
if (presence) {
|
|
686
|
-
ev.emit('presence.update', { id: jid, presences: { [participant]: presence } })
|
|
666
|
+
ev.emit('presence.update', { id: jid, presences: { [participant]: presence } })
|
|
687
667
|
}
|
|
688
|
-
}
|
|
668
|
+
}
|
|
669
|
+
|
|
689
670
|
const appPatch = async (patchCreate) => {
|
|
690
|
-
const name = patchCreate.type
|
|
691
|
-
const myAppStateKeyId = authState.creds.myAppStateKeyId
|
|
671
|
+
const name = patchCreate.type
|
|
672
|
+
const myAppStateKeyId = authState.creds.myAppStateKeyId
|
|
673
|
+
|
|
692
674
|
if (!myAppStateKeyId) {
|
|
693
|
-
throw new Boom('App state key not present!', { statusCode: 400 })
|
|
675
|
+
throw new boom_1.Boom('App state key not present!', { statusCode: 400 })
|
|
694
676
|
}
|
|
695
|
-
|
|
696
|
-
let
|
|
697
|
-
|
|
677
|
+
|
|
678
|
+
let initial
|
|
679
|
+
let encodeResult
|
|
680
|
+
|
|
681
|
+
await processingMutex.mutex(async () => {
|
|
698
682
|
await authState.keys.transaction(async () => {
|
|
699
|
-
logger.debug({ patch: patchCreate }, 'applying app patch')
|
|
700
|
-
await resyncAppState([name], false)
|
|
701
|
-
const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name])
|
|
702
|
-
initial = currentSyncVersion
|
|
703
|
-
encodeResult = await encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey)
|
|
704
|
-
const { patch, state } = encodeResult
|
|
683
|
+
logger.debug({ patch: patchCreate }, 'applying app patch')
|
|
684
|
+
await resyncAppState([name], false)
|
|
685
|
+
const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name])
|
|
686
|
+
initial = currentSyncVersion || Utils_1.newLTHashState()
|
|
687
|
+
encodeResult = await Utils_1.encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey)
|
|
688
|
+
const { patch, state } = encodeResult
|
|
689
|
+
|
|
705
690
|
const node = {
|
|
706
691
|
tag: 'iq',
|
|
707
692
|
attrs: {
|
|
708
|
-
to: S_WHATSAPP_NET,
|
|
693
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
709
694
|
type: 'set',
|
|
710
695
|
xmlns: 'w:sync:app:state'
|
|
711
696
|
},
|
|
@@ -719,94 +704,88 @@ export const makeChatsSocket = (config) => {
|
|
|
719
704
|
attrs: {
|
|
720
705
|
name,
|
|
721
706
|
version: (state.version - 1).toString(),
|
|
722
|
-
return_snapshot: 'false'
|
|
707
|
+
'return_snapshot': 'false'
|
|
723
708
|
},
|
|
724
709
|
content: [
|
|
725
710
|
{
|
|
726
711
|
tag: 'patch',
|
|
727
712
|
attrs: {},
|
|
728
|
-
content: proto.SyncdPatch.encode(patch).finish()
|
|
713
|
+
content: WAProto_1.proto.SyncdPatch.encode(patch).finish()
|
|
729
714
|
}
|
|
730
715
|
]
|
|
731
716
|
}
|
|
732
717
|
]
|
|
733
718
|
}
|
|
734
719
|
]
|
|
735
|
-
}
|
|
736
|
-
await query(node)
|
|
737
|
-
await authState.keys.set({ 'app-state-sync-version': { [name]: state } })
|
|
738
|
-
}, authState?.creds?.me?.id || 'app-patch')
|
|
739
|
-
})
|
|
720
|
+
}
|
|
721
|
+
await query(node)
|
|
722
|
+
await authState.keys.set({ 'app-state-sync-version': { [name]: state } })
|
|
723
|
+
}, authState?.creds?.me?.id || 'app-patch')
|
|
724
|
+
})
|
|
725
|
+
|
|
740
726
|
if (config.emitOwnEvents) {
|
|
741
|
-
const { onMutation } = newAppStateChunkHandler(false)
|
|
742
|
-
const { mutationMap } = await decodePatches(name, [{ ...encodeResult.patch, version: { version: encodeResult.state.version } }], initial, getAppStateSyncKey, config.options, undefined, logger)
|
|
727
|
+
const { onMutation } = newAppStateChunkHandler(false)
|
|
728
|
+
const { mutationMap } = await Utils_1.decodePatches(name, [{ ...encodeResult.patch, version: { version: encodeResult.state.version }, }], initial, getAppStateSyncKey, config.options, undefined, logger)
|
|
729
|
+
|
|
743
730
|
for (const key in mutationMap) {
|
|
744
|
-
onMutation(mutationMap[key])
|
|
731
|
+
onMutation(mutationMap[key])
|
|
745
732
|
}
|
|
746
733
|
}
|
|
747
|
-
}
|
|
748
|
-
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/** sending non-abt props may fix QR scan fail if server expects */
|
|
749
737
|
const fetchProps = async () => {
|
|
750
738
|
const resultNode = await query({
|
|
751
739
|
tag: 'iq',
|
|
752
740
|
attrs: {
|
|
753
|
-
to: S_WHATSAPP_NET,
|
|
754
|
-
xmlns: '
|
|
755
|
-
type: 'get'
|
|
741
|
+
to: WABinary_1.S_WHATSAPP_NET,
|
|
742
|
+
xmlns: 'w',
|
|
743
|
+
type: 'get',
|
|
756
744
|
},
|
|
757
745
|
content: [
|
|
758
|
-
{
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
...(authState?.creds?.lastPropHash ? { hash: authState.creds.lastPropHash } : {})
|
|
763
|
-
}
|
|
764
|
-
}
|
|
746
|
+
{ tag: 'props', attrs: {
|
|
747
|
+
protocol: '2',
|
|
748
|
+
hash: authState?.creds?.lastPropHash || ''
|
|
749
|
+
} }
|
|
765
750
|
]
|
|
766
|
-
})
|
|
767
|
-
|
|
768
|
-
|
|
751
|
+
})
|
|
752
|
+
|
|
753
|
+
const propsNode = WABinary_1.getBinaryNodeChild(resultNode, 'props')
|
|
754
|
+
let props = {}
|
|
755
|
+
|
|
769
756
|
if (propsNode) {
|
|
770
|
-
if (propsNode.attrs?.hash) {
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
ev.emit('creds.update', authState.creds);
|
|
757
|
+
if (propsNode.attrs?.hash) { // on some clients, the hash is returning as undefined
|
|
758
|
+
authState.creds.lastPropHash = propsNode?.attrs?.hash
|
|
759
|
+
ev.emit('creds.update', authState.creds)
|
|
774
760
|
}
|
|
775
|
-
|
|
761
|
+
|
|
762
|
+
props = WABinary_1.reduceBinaryNodeToDictionary(propsNode, 'prop')
|
|
776
763
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
}
|
|
782
|
-
const profilePicProp = props['9666'] ?? props['profile_scraping_privacy_token_in_photo_iq'];
|
|
783
|
-
if (profilePicProp !== undefined) {
|
|
784
|
-
serverProps.profilePicPrivacyToken = profilePicProp === 'true' || profilePicProp === '1';
|
|
785
|
-
}
|
|
786
|
-
const lidIssueProp = props['14303'] ?? props['lid_trusted_token_issue_to_lid'];
|
|
787
|
-
if (lidIssueProp !== undefined) {
|
|
788
|
-
serverProps.lidTrustedTokenIssueToLid = lidIssueProp === 'true' || lidIssueProp === '1';
|
|
789
|
-
}
|
|
790
|
-
logger.debug({ serverProps }, 'fetched props');
|
|
791
|
-
return props;
|
|
792
|
-
};
|
|
764
|
+
logger.debug('fetched props')
|
|
765
|
+
return props
|
|
766
|
+
}
|
|
767
|
+
|
|
793
768
|
/**
|
|
794
769
|
* modify a chat -- mark unread, read etc.
|
|
795
770
|
* lastMessages must be sorted in reverse chronologically
|
|
796
|
-
* requires the last messages till the last message received
|
|
797
|
-
|
|
771
|
+
* requires the last messages till the last message received required for archive & unread
|
|
772
|
+
*/
|
|
798
773
|
const chatModify = (mod, jid) => {
|
|
799
|
-
const patch = chatModificationToAppPatch(mod, jid)
|
|
800
|
-
return appPatch(patch)
|
|
801
|
-
}
|
|
774
|
+
const patch = Utils_1.chatModificationToAppPatch(mod, jid)
|
|
775
|
+
return appPatch(patch)
|
|
776
|
+
}
|
|
777
|
+
|
|
802
778
|
/**
|
|
803
779
|
* Enable/Disable link preview privacy, not related to baileys link preview generation
|
|
804
780
|
*/
|
|
805
781
|
const updateDisableLinkPreviewsPrivacy = (isPreviewsDisabled) => {
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
782
|
+
return chatModify({
|
|
783
|
+
disableLinkPreviews: {
|
|
784
|
+
isPreviewsDisabled
|
|
785
|
+
}
|
|
786
|
+
}, '')
|
|
787
|
+
}
|
|
788
|
+
|
|
810
789
|
/**
|
|
811
790
|
* Star or Unstar a message
|
|
812
791
|
*/
|
|
@@ -816,24 +795,27 @@ export const makeChatsSocket = (config) => {
|
|
|
816
795
|
messages,
|
|
817
796
|
star
|
|
818
797
|
}
|
|
819
|
-
}, jid)
|
|
820
|
-
}
|
|
798
|
+
}, jid)
|
|
799
|
+
}
|
|
800
|
+
|
|
821
801
|
/**
|
|
822
|
-
* Add
|
|
802
|
+
* Add Or Edit Contact
|
|
823
803
|
*/
|
|
824
804
|
const addOrEditContact = (jid, contact) => {
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
}, jid)
|
|
828
|
-
}
|
|
805
|
+
return chatModify({
|
|
806
|
+
contact
|
|
807
|
+
}, jid)
|
|
808
|
+
}
|
|
809
|
+
|
|
829
810
|
/**
|
|
830
811
|
* Remove Contact
|
|
831
812
|
*/
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
813
|
+
const removeContact = (jid) => {
|
|
814
|
+
return chatModify({
|
|
815
|
+
contact: null
|
|
816
|
+
}, jid)
|
|
817
|
+
}
|
|
818
|
+
|
|
837
819
|
/**
|
|
838
820
|
* Adds label
|
|
839
821
|
*/
|
|
@@ -842,8 +824,9 @@ export const makeChatsSocket = (config) => {
|
|
|
842
824
|
addLabel: {
|
|
843
825
|
...labels
|
|
844
826
|
}
|
|
845
|
-
}, jid)
|
|
846
|
-
}
|
|
827
|
+
}, jid)
|
|
828
|
+
}
|
|
829
|
+
|
|
847
830
|
/**
|
|
848
831
|
* Adds label for the chats
|
|
849
832
|
*/
|
|
@@ -852,8 +835,9 @@ export const makeChatsSocket = (config) => {
|
|
|
852
835
|
addChatLabel: {
|
|
853
836
|
labelId
|
|
854
837
|
}
|
|
855
|
-
}, jid)
|
|
856
|
-
}
|
|
838
|
+
}, jid)
|
|
839
|
+
}
|
|
840
|
+
|
|
857
841
|
/**
|
|
858
842
|
* Removes label for the chat
|
|
859
843
|
*/
|
|
@@ -862,8 +846,9 @@ export const makeChatsSocket = (config) => {
|
|
|
862
846
|
removeChatLabel: {
|
|
863
847
|
labelId
|
|
864
848
|
}
|
|
865
|
-
}, jid)
|
|
866
|
-
}
|
|
849
|
+
}, jid)
|
|
850
|
+
}
|
|
851
|
+
|
|
867
852
|
/**
|
|
868
853
|
* Adds label for the message
|
|
869
854
|
*/
|
|
@@ -873,8 +858,9 @@ export const makeChatsSocket = (config) => {
|
|
|
873
858
|
messageId,
|
|
874
859
|
labelId
|
|
875
860
|
}
|
|
876
|
-
}, jid)
|
|
877
|
-
}
|
|
861
|
+
}, jid)
|
|
862
|
+
}
|
|
863
|
+
|
|
878
864
|
/**
|
|
879
865
|
* Removes label for the message
|
|
880
866
|
*/
|
|
@@ -884,129 +870,114 @@ export const makeChatsSocket = (config) => {
|
|
|
884
870
|
messageId,
|
|
885
871
|
labelId
|
|
886
872
|
}
|
|
887
|
-
}, jid)
|
|
888
|
-
}
|
|
873
|
+
}, jid)
|
|
874
|
+
}
|
|
875
|
+
|
|
889
876
|
/**
|
|
877
|
+
* Removes Chats
|
|
878
|
+
*/
|
|
879
|
+
const clearMessage = (jid, key, timeStamp) => {
|
|
880
|
+
return chatModify({
|
|
881
|
+
delete: true,
|
|
882
|
+
lastMessages: [{
|
|
883
|
+
key: key,
|
|
884
|
+
messageTimestamp: timeStamp
|
|
885
|
+
}],
|
|
886
|
+
}, jid)
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
890
|
* Add or Edit Quick Reply
|
|
891
891
|
*/
|
|
892
892
|
const addOrEditQuickReply = (quickReply) => {
|
|
893
893
|
return chatModify({
|
|
894
894
|
quickReply
|
|
895
|
-
}, '')
|
|
896
|
-
}
|
|
895
|
+
}, '')
|
|
896
|
+
}
|
|
897
|
+
|
|
897
898
|
/**
|
|
898
899
|
* Remove Quick Reply
|
|
899
900
|
*/
|
|
900
901
|
const removeQuickReply = (timestamp) => {
|
|
901
902
|
return chatModify({
|
|
902
903
|
quickReply: { timestamp, deleted: true }
|
|
903
|
-
}, '')
|
|
904
|
-
}
|
|
904
|
+
}, '')
|
|
905
|
+
}
|
|
906
|
+
|
|
905
907
|
/**
|
|
906
908
|
* queries need to be fired on connection open
|
|
907
909
|
* help ensure parity with WA Web
|
|
908
910
|
* */
|
|
909
911
|
const executeInitQueries = async () => {
|
|
910
|
-
await Promise.all([
|
|
911
|
-
|
|
912
|
+
await Promise.all([
|
|
913
|
+
fetchProps(),
|
|
914
|
+
fetchBlocklist(),
|
|
915
|
+
fetchPrivacySettings(),
|
|
916
|
+
])
|
|
917
|
+
}
|
|
918
|
+
|
|
912
919
|
const upsertMessage = ev.createBufferedFunction(async (msg, type) => {
|
|
913
|
-
ev.emit('messages.upsert', { messages: [msg], type })
|
|
920
|
+
ev.emit('messages.upsert', { messages: [msg], type })
|
|
914
921
|
if (!!msg.pushName) {
|
|
915
|
-
let jid = msg.key.fromMe ? authState.creds.me.id : msg.key.participant || msg.key.remoteJid
|
|
916
|
-
jid = jidNormalizedUser(jid)
|
|
922
|
+
let jid = msg.key.fromMe ? authState.creds.me.id : (msg.key.participant || msg.key.remoteJid)
|
|
923
|
+
jid = WABinary_1.jidNormalizedUser(jid)
|
|
924
|
+
|
|
917
925
|
if (!msg.key.fromMe) {
|
|
918
|
-
ev.emit('contacts.update', [{ id: jid, notify: msg.pushName, verifiedName: msg.verifiedBizName }])
|
|
926
|
+
ev.emit('contacts.update', [{ id: jid, notify: msg.pushName, verifiedName: msg.verifiedBizName }])
|
|
919
927
|
}
|
|
928
|
+
|
|
920
929
|
// update our pushname too
|
|
921
930
|
if (msg.key.fromMe && msg.pushName && authState.creds.me?.name !== msg.pushName) {
|
|
922
|
-
ev.emit('creds.update', { me: { ...authState.creds.me, name: msg.pushName } })
|
|
931
|
+
ev.emit('creds.update', { me: { ...authState.creds.me, name: msg.pushName } })
|
|
923
932
|
}
|
|
924
933
|
}
|
|
925
|
-
|
|
934
|
+
|
|
935
|
+
const historyMsg = Utils_1.getHistoryMsg(msg.message)
|
|
926
936
|
const shouldProcessHistoryMsg = historyMsg
|
|
927
|
-
? shouldSyncHistoryMessage(historyMsg)
|
|
928
|
-
PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType)
|
|
929
|
-
: false
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
// INITIAL_BOOTSTRAP — fire immediately, no progress check (same as WA Web K function)
|
|
933
|
-
if (syncType === proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP &&
|
|
934
|
-
!historySyncStatus.initialBootstrapComplete) {
|
|
935
|
-
historySyncStatus.initialBootstrapComplete = true;
|
|
936
|
-
ev.emit('messaging-history.status', {
|
|
937
|
-
syncType,
|
|
938
|
-
status: 'complete',
|
|
939
|
-
explicit: true
|
|
940
|
-
});
|
|
941
|
-
}
|
|
942
|
-
// RECENT with progress === 100 — explicit completion
|
|
943
|
-
if (syncType === proto.HistorySync.HistorySyncType.RECENT &&
|
|
944
|
-
historyMsg.progress === 100 &&
|
|
945
|
-
!historySyncStatus.recentSyncComplete) {
|
|
946
|
-
historySyncStatus.recentSyncComplete = true;
|
|
947
|
-
clearTimeout(historySyncPausedTimeout);
|
|
948
|
-
historySyncPausedTimeout = undefined;
|
|
949
|
-
ev.emit('messaging-history.status', {
|
|
950
|
-
syncType,
|
|
951
|
-
status: 'complete',
|
|
952
|
-
explicit: true
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
// Reset 120s paused timeout on any RECENT chunk (like WA Web's handleChunkProgress)
|
|
956
|
-
if (syncType === proto.HistorySync.HistorySyncType.RECENT && !historySyncStatus.recentSyncComplete) {
|
|
957
|
-
clearTimeout(historySyncPausedTimeout);
|
|
958
|
-
historySyncPausedTimeout = setTimeout(() => {
|
|
959
|
-
if (!historySyncStatus.recentSyncComplete) {
|
|
960
|
-
historySyncStatus.recentSyncComplete = true;
|
|
961
|
-
ev.emit('messaging-history.status', {
|
|
962
|
-
syncType: proto.HistorySync.HistorySyncType.RECENT,
|
|
963
|
-
status: 'paused',
|
|
964
|
-
explicit: false
|
|
965
|
-
});
|
|
966
|
-
}
|
|
967
|
-
historySyncPausedTimeout = undefined;
|
|
968
|
-
}, HISTORY_SYNC_PAUSED_TIMEOUT_MS);
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
// State machine: decide on sync and flush
|
|
972
|
-
if (historyMsg && syncState === SyncState.AwaitingInitialSync) {
|
|
937
|
+
? (shouldSyncHistoryMessage(historyMsg)
|
|
938
|
+
&& Defaults_1.PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType))
|
|
939
|
+
: false
|
|
940
|
+
|
|
941
|
+
if (historyMsg && syncState === Types_1.SyncState.AwaitingInitialSync) {
|
|
973
942
|
if (awaitingSyncTimeout) {
|
|
974
|
-
|
|
975
|
-
|
|
943
|
+
clearTimeout(awaitingSyncTimeout)
|
|
944
|
+
awaitingSyncTimeout = undefined
|
|
976
945
|
}
|
|
946
|
+
|
|
977
947
|
if (shouldProcessHistoryMsg) {
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
ev.flush();
|
|
948
|
+
syncState = Types_1.SyncState.Syncing
|
|
949
|
+
logger.info('Transitioned to Syncing state')
|
|
950
|
+
// Let doAppStateSync handle the final flush after it`s done
|
|
951
|
+
} else {
|
|
952
|
+
syncState = Types_1.SyncState.Online
|
|
953
|
+
logger.info('History sync skipped, transitioning to Online state and flushing buffer')
|
|
954
|
+
ev.flush()
|
|
986
955
|
}
|
|
987
956
|
}
|
|
957
|
+
|
|
988
958
|
const doAppStateSync = async () => {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
}
|
|
959
|
+
if (syncState === Types_1.SyncState.Syncing) {
|
|
960
|
+
logger.info('Doing app state sync')
|
|
961
|
+
await resyncAppState(Types_1.ALL_WA_PATCH_NAMES, true)
|
|
962
|
+
|
|
963
|
+
// Sync is complete, go online and flush everything
|
|
964
|
+
syncState = Types_1.SyncState.Online
|
|
965
|
+
logger.info('App state sync complete, transitioning to Online state and flushing buffer')
|
|
966
|
+
ev.flush()
|
|
967
|
+
|
|
968
|
+
const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1
|
|
969
|
+
ev.emit('creds.update', { accountSyncCounter })
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
1002
973
|
await Promise.all([
|
|
1003
974
|
(async () => {
|
|
1004
975
|
if (shouldProcessHistoryMsg) {
|
|
1005
|
-
await doAppStateSync()
|
|
976
|
+
await doAppStateSync()
|
|
1006
977
|
}
|
|
1007
978
|
})(),
|
|
1008
|
-
processMessage(msg, {
|
|
1009
|
-
|
|
979
|
+
Utils_1.processMessage(msg, {
|
|
980
|
+
signalRepository,
|
|
1010
981
|
shouldProcessHistoryMsg,
|
|
1011
982
|
placeholderResendCache,
|
|
1012
983
|
ev,
|
|
@@ -1014,147 +985,101 @@ export const makeChatsSocket = (config) => {
|
|
|
1014
985
|
keyStore: authState.keys,
|
|
1015
986
|
logger,
|
|
1016
987
|
options: config.options,
|
|
1017
|
-
getMessage
|
|
988
|
+
getMessage: config.getMessage,
|
|
1018
989
|
})
|
|
1019
|
-
])
|
|
1020
|
-
|
|
1021
|
-
if (msg.message?.protocolMessage?.appStateSyncKeyShare && syncState === SyncState.Syncing) {
|
|
1022
|
-
|
|
1023
|
-
|
|
990
|
+
])
|
|
991
|
+
|
|
992
|
+
if (msg.message?.protocolMessage?.appStateSyncKeyShare && syncState === Types_1.SyncState.Syncing) {
|
|
993
|
+
logger.info('App state sync key arrived, triggering app state sync')
|
|
994
|
+
await doAppStateSync()
|
|
1024
995
|
}
|
|
1025
|
-
})
|
|
1026
|
-
|
|
1027
|
-
ws.on('CB:
|
|
996
|
+
})
|
|
997
|
+
|
|
998
|
+
ws.on('CB:presence', handlePresenceUpdate)
|
|
999
|
+
ws.on('CB:chatstate', handlePresenceUpdate)
|
|
1028
1000
|
ws.on('CB:ib,,dirty', async (node) => {
|
|
1029
|
-
const { attrs } = getBinaryNodeChild(node, 'dirty')
|
|
1030
|
-
const type = attrs.type
|
|
1001
|
+
const { attrs } = WABinary_1.getBinaryNodeChild(node, 'dirty')
|
|
1002
|
+
const type = attrs.type
|
|
1003
|
+
|
|
1031
1004
|
switch (type) {
|
|
1032
1005
|
case 'account_sync':
|
|
1033
1006
|
if (attrs.timestamp) {
|
|
1034
|
-
let { lastAccountSyncTimestamp } = authState.creds
|
|
1007
|
+
let { lastAccountSyncTimestamp } = authState.creds
|
|
1035
1008
|
if (lastAccountSyncTimestamp) {
|
|
1036
|
-
await cleanDirtyBits('account_sync', lastAccountSyncTimestamp)
|
|
1009
|
+
await cleanDirtyBits('account_sync', lastAccountSyncTimestamp)
|
|
1037
1010
|
}
|
|
1038
|
-
lastAccountSyncTimestamp = +attrs.timestamp
|
|
1039
|
-
ev.emit('creds.update', { lastAccountSyncTimestamp })
|
|
1011
|
+
lastAccountSyncTimestamp = +attrs.timestamp
|
|
1012
|
+
ev.emit('creds.update', { lastAccountSyncTimestamp })
|
|
1040
1013
|
}
|
|
1041
|
-
break
|
|
1014
|
+
break
|
|
1042
1015
|
case 'groups':
|
|
1043
|
-
|
|
1044
|
-
|
|
1016
|
+
await groupFetchAllParticipating()
|
|
1017
|
+
await cleanDirtyBits('groups')
|
|
1018
|
+
break
|
|
1045
1019
|
default:
|
|
1046
|
-
logger.info({ node }, 'received unknown sync')
|
|
1047
|
-
break
|
|
1020
|
+
logger.info({ node }, 'received unknown sync')
|
|
1021
|
+
break
|
|
1048
1022
|
}
|
|
1049
|
-
})
|
|
1023
|
+
})
|
|
1024
|
+
|
|
1050
1025
|
ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
|
|
1051
|
-
if (connection === 'close') {
|
|
1052
|
-
blockedCollections.clear();
|
|
1053
|
-
clearTimeout(historySyncPausedTimeout);
|
|
1054
|
-
historySyncPausedTimeout = undefined;
|
|
1055
|
-
}
|
|
1056
1026
|
if (connection === 'open') {
|
|
1057
1027
|
if (fireInitQueries) {
|
|
1058
|
-
executeInitQueries()
|
|
1028
|
+
executeInitQueries()
|
|
1029
|
+
.catch(error => onUnexpectedError(error, 'init queries'))
|
|
1059
1030
|
}
|
|
1060
|
-
sendPresenceUpdate(markOnlineOnConnect ? 'available' : 'unavailable')
|
|
1031
|
+
sendPresenceUpdate(markOnlineOnConnect ? 'available' : 'unavailable')
|
|
1032
|
+
.catch(error => onUnexpectedError(error, 'presence update requests'))
|
|
1061
1033
|
}
|
|
1062
|
-
|
|
1063
|
-
|
|
1034
|
+
|
|
1035
|
+
if (!receivedPendingNotifications || syncState !== Types_1.SyncState.Connecting) {
|
|
1036
|
+
return
|
|
1064
1037
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
}));
|
|
1038
|
+
|
|
1039
|
+
syncState = Types_1.AwaitingInitialSync
|
|
1040
|
+
logger.info('Connection is now AwaitingInitialSync, buffering events')
|
|
1041
|
+
ev.buffer()
|
|
1042
|
+
|
|
1043
|
+
const willSyncHistory = shouldSyncHistoryMessage(WAProto_1.proto.Message.HistorySyncNotification.fromObject({
|
|
1044
|
+
syncType: WAProto_1.proto.HistorySync.HistorySyncType.RECENT
|
|
1045
|
+
}))
|
|
1046
|
+
|
|
1075
1047
|
if (!willSyncHistory) {
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1048
|
+
logger.info('History sync is disabled by config, not waiting for notification. Transitioning to Online.')
|
|
1049
|
+
syncState = Types_1.SyncState.Online
|
|
1050
|
+
setTimeout(() => ev.flush(), 0)
|
|
1051
|
+
return
|
|
1080
1052
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
if (authState.creds.accountSyncCounter > 0) {
|
|
1085
|
-
logger.info('Reconnection with existing sync data, skipping history sync wait. Transitioning to Online.');
|
|
1086
|
-
syncState = SyncState.Online;
|
|
1087
|
-
setTimeout(() => ev.flush(), 0);
|
|
1088
|
-
return;
|
|
1089
|
-
}
|
|
1090
|
-
logger.info('First connection, awaiting history sync notification with a 20s timeout.');
|
|
1053
|
+
|
|
1054
|
+
logger.info('History sync is enabled, awaiting notification with a 20s timeout.')
|
|
1055
|
+
|
|
1091
1056
|
if (awaitingSyncTimeout) {
|
|
1092
|
-
|
|
1057
|
+
clearTimeout(awaitingSyncTimeout)
|
|
1093
1058
|
}
|
|
1059
|
+
|
|
1094
1060
|
awaitingSyncTimeout = setTimeout(() => {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
ev.emit('creds.update', { accountSyncCounter });
|
|
1104
|
-
}
|
|
1105
|
-
}, 20000);
|
|
1106
|
-
});
|
|
1107
|
-
// When an app state sync key arrives (myAppStateKeyId is set) and there are
|
|
1108
|
-
// collections blocked on a missing key, trigger a re-sync for just those collections.
|
|
1109
|
-
// This mirrors WA Web's Blocked → retry-on-key-arrival behavior.
|
|
1110
|
-
ev.on('creds.update', ({ myAppStateKeyId }) => {
|
|
1111
|
-
if (!myAppStateKeyId || blockedCollections.size === 0) {
|
|
1112
|
-
return;
|
|
1113
|
-
}
|
|
1114
|
-
// If we're in the middle of a full sync, doAppStateSync handles all collections
|
|
1115
|
-
if (syncState === SyncState.Syncing) {
|
|
1116
|
-
blockedCollections.clear();
|
|
1117
|
-
return;
|
|
1118
|
-
}
|
|
1119
|
-
const collections = [...blockedCollections];
|
|
1120
|
-
blockedCollections.clear();
|
|
1121
|
-
logger.info({ collections }, 'app state sync key arrived, re-syncing blocked collections');
|
|
1122
|
-
resyncAppState(collections, false).catch(error => onUnexpectedError(error, 'blocked collections resync'));
|
|
1123
|
-
});
|
|
1124
|
-
ev.on('lid-mapping.update', async ({ lid, pn }) => {
|
|
1125
|
-
try {
|
|
1126
|
-
await signalRepository.lidMapping.storeLIDPNMappings([{ lid, pn }]);
|
|
1127
|
-
}
|
|
1128
|
-
catch (error) {
|
|
1129
|
-
logger.warn({ lid, pn, error }, 'Failed to store LID-PN mapping');
|
|
1130
|
-
}
|
|
1131
|
-
});
|
|
1132
|
-
registerSocketEndHandler(() => {
|
|
1133
|
-
if (awaitingSyncTimeout) {
|
|
1134
|
-
clearTimeout(awaitingSyncTimeout);
|
|
1135
|
-
awaitingSyncTimeout = undefined;
|
|
1136
|
-
}
|
|
1137
|
-
if (!config.placeholderResendCache && placeholderResendCache.close) {
|
|
1138
|
-
placeholderResendCache.close();
|
|
1139
|
-
}
|
|
1140
|
-
syncState = SyncState.Connecting;
|
|
1141
|
-
privacySettings = undefined;
|
|
1142
|
-
});
|
|
1061
|
+
if (syncState === Types_1.SyncState.AwaitingInitialSync) {
|
|
1062
|
+
logger.warn('Timeout in AwaitingInitialSync, forcing state to Online and flushing buffer')
|
|
1063
|
+
syncState = Types_1.SyncState.Online
|
|
1064
|
+
ev.flush()
|
|
1065
|
+
}
|
|
1066
|
+
}, 20_000)
|
|
1067
|
+
})
|
|
1068
|
+
|
|
1143
1069
|
return {
|
|
1144
|
-
...sock,
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
receiptMutex,
|
|
1150
|
-
appStatePatchMutex,
|
|
1151
|
-
notificationMutex,
|
|
1070
|
+
...sock,
|
|
1071
|
+
star,
|
|
1072
|
+
addOrEditContact,
|
|
1073
|
+
removeContact,
|
|
1074
|
+
processingMutex,
|
|
1152
1075
|
fetchPrivacySettings,
|
|
1153
1076
|
upsertMessage,
|
|
1154
1077
|
appPatch,
|
|
1078
|
+
createCallLink,
|
|
1155
1079
|
sendPresenceUpdate,
|
|
1156
|
-
presenceSubscribe,
|
|
1157
|
-
|
|
1080
|
+
presenceSubscribe,
|
|
1081
|
+
getBotListV2,
|
|
1082
|
+
getLidUser,
|
|
1158
1083
|
fetchBlocklist,
|
|
1159
1084
|
fetchStatus,
|
|
1160
1085
|
fetchDisappearingDuration,
|
|
@@ -1163,9 +1088,8 @@ export const makeChatsSocket = (config) => {
|
|
|
1163
1088
|
updateProfileStatus,
|
|
1164
1089
|
updateProfileName,
|
|
1165
1090
|
updateBlockStatus,
|
|
1166
|
-
updateDisableLinkPreviewsPrivacy,
|
|
1167
1091
|
updateCallPrivacy,
|
|
1168
|
-
updateMessagesPrivacy,
|
|
1092
|
+
updateMessagesPrivacy,
|
|
1169
1093
|
updateLastSeenPrivacy,
|
|
1170
1094
|
updateOnlinePrivacy,
|
|
1171
1095
|
updateProfilePicturePrivacy,
|
|
@@ -1173,21 +1097,22 @@ export const makeChatsSocket = (config) => {
|
|
|
1173
1097
|
updateReadReceiptsPrivacy,
|
|
1174
1098
|
updateGroupsAddPrivacy,
|
|
1175
1099
|
updateDefaultDisappearingMode,
|
|
1100
|
+
updateDisableLinkPreviewsPrivacy,
|
|
1176
1101
|
getBusinessProfile,
|
|
1177
1102
|
resyncAppState,
|
|
1178
1103
|
chatModify,
|
|
1179
1104
|
cleanDirtyBits,
|
|
1180
|
-
addOrEditContact,
|
|
1181
|
-
removeContact,
|
|
1182
|
-
placeholderResendCache,
|
|
1183
1105
|
addLabel,
|
|
1184
1106
|
addChatLabel,
|
|
1185
1107
|
removeChatLabel,
|
|
1186
1108
|
addMessageLabel,
|
|
1187
1109
|
removeMessageLabel,
|
|
1188
|
-
|
|
1110
|
+
clearMessage,
|
|
1189
1111
|
addOrEditQuickReply,
|
|
1190
1112
|
removeQuickReply
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
module.exports = {
|
|
1117
|
+
makeChatsSocket
|
|
1118
|
+
}
|