violetics 7.0.0-alpha → 7.0.2-alpha
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 +3 -2
- package/README.md +1001 -232
- package/WAProto/index.js +75379 -142631
- package/engine-requirements.js +11 -8
- package/lib/Defaults/index.js +132 -144
- package/lib/Signal/Group/ciphertext-message.js +2 -6
- package/lib/Signal/Group/group-session-builder.js +7 -42
- package/lib/Signal/Group/group_cipher.js +37 -52
- package/lib/Signal/Group/index.js +11 -57
- package/lib/Signal/Group/keyhelper.js +7 -45
- package/lib/Signal/Group/sender-chain-key.js +7 -16
- package/lib/Signal/Group/sender-key-distribution-message.js +8 -12
- package/lib/Signal/Group/sender-key-message.js +9 -13
- package/lib/Signal/Group/sender-key-name.js +2 -6
- package/lib/Signal/Group/sender-key-record.js +9 -22
- package/lib/Signal/Group/sender-key-state.js +27 -43
- package/lib/Signal/Group/sender-message-key.js +4 -8
- package/lib/Signal/libsignal.js +319 -94
- package/lib/Signal/lid-mapping.js +224 -139
- package/lib/Socket/Client/index.js +2 -19
- package/lib/Socket/Client/types.js +10 -0
- package/lib/Socket/Client/websocket.js +53 -0
- package/lib/Socket/business.js +162 -44
- package/lib/Socket/chats.js +477 -442
- package/lib/Socket/communities.js +430 -0
- package/lib/Socket/groups.js +110 -99
- package/lib/Socket/index.js +10 -10
- package/lib/Socket/messages-recv.js +878 -552
- package/lib/Socket/messages-send.js +859 -428
- package/lib/Socket/mex.js +41 -0
- package/lib/Socket/newsletter.js +195 -390
- package/lib/Socket/socket.js +463 -289
- package/lib/Store/index.js +3 -10
- package/lib/Store/make-in-memory-store.js +73 -79
- package/lib/Store/make-ordered-dictionary.js +4 -7
- package/lib/Store/object-repository.js +2 -6
- package/lib/Types/Auth.js +1 -2
- package/lib/Types/Bussines.js +1 -0
- package/lib/Types/Call.js +1 -2
- package/lib/Types/Chat.js +7 -4
- package/lib/Types/Contact.js +1 -2
- package/lib/Types/Events.js +1 -2
- package/lib/Types/GroupMetadata.js +1 -2
- package/lib/Types/Label.js +2 -5
- package/lib/Types/LabelAssociation.js +2 -5
- package/lib/Types/Message.js +17 -9
- package/lib/Types/Newsletter.js +33 -38
- package/lib/Types/Product.js +1 -2
- package/lib/Types/Signal.js +1 -2
- package/lib/Types/Socket.js +2 -2
- package/lib/Types/State.js +12 -2
- package/lib/Types/USync.js +1 -2
- package/lib/Types/index.js +14 -31
- package/lib/Utils/auth-utils.js +228 -145
- package/lib/Utils/browser-utils.js +28 -0
- package/lib/Utils/business.js +66 -70
- package/lib/Utils/chat-utils.js +331 -249
- package/lib/Utils/crypto.js +57 -91
- package/lib/Utils/decode-wa-message.js +168 -84
- package/lib/Utils/event-buffer.js +138 -80
- package/lib/Utils/generics.js +180 -297
- package/lib/Utils/history.js +83 -49
- package/lib/Utils/identity-change-handler.js +48 -0
- package/lib/Utils/index.js +19 -33
- package/lib/Utils/link-preview.js +14 -23
- package/lib/Utils/logger.js +2 -7
- package/lib/Utils/lt-hash.js +2 -46
- package/lib/Utils/make-mutex.js +24 -35
- package/lib/Utils/message-retry-manager.js +224 -0
- package/lib/Utils/messages-media.js +501 -496
- package/lib/Utils/messages.js +1428 -362
- package/lib/Utils/noise-handler.js +145 -100
- package/lib/Utils/pre-key-manager.js +105 -0
- package/lib/Utils/process-message.js +356 -150
- package/lib/Utils/reporting-utils.js +257 -0
- package/lib/Utils/signal.js +78 -73
- package/lib/Utils/sync-action-utils.js +47 -0
- package/lib/Utils/tc-token-utils.js +17 -0
- package/lib/Utils/use-multi-file-auth-state.js +32 -34
- package/lib/Utils/validate-connection.js +91 -107
- package/lib/WABinary/constants.js +1300 -1304
- package/lib/WABinary/decode.js +26 -48
- package/lib/WABinary/encode.js +109 -155
- package/lib/WABinary/generic-utils.js +161 -149
- package/lib/WABinary/index.js +5 -21
- package/lib/WABinary/jid-utils.js +73 -40
- package/lib/WABinary/types.js +1 -2
- package/lib/WAM/BinaryInfo.js +2 -6
- package/lib/WAM/constants.js +19070 -11568
- package/lib/WAM/encode.js +17 -23
- package/lib/WAM/index.js +3 -19
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +8 -12
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +11 -15
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +9 -13
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +9 -14
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +20 -23
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +13 -9
- package/lib/WAUSync/Protocols/index.js +4 -20
- package/lib/WAUSync/USyncQuery.js +40 -36
- package/lib/WAUSync/USyncUser.js +2 -6
- package/lib/WAUSync/index.js +3 -19
- package/lib/index.js +11 -44
- package/package.json +75 -108
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Signal/Group/queue-job.js +0 -57
- package/lib/Socket/Client/abstract-socket-client.js +0 -13
- package/lib/Socket/Client/mobile-socket-client.js +0 -65
- package/lib/Socket/Client/web-socket-client.js +0 -111
- package/lib/Socket/groupStatus.js +0 -637
- package/lib/Socket/registration.js +0 -166
- package/lib/Socket/usync.js +0 -70
- package/lib/Store/make-cache-manager-store.js +0 -83
- package/lib/Utils/baileys-event-stream.js +0 -63
package/lib/Socket/chats.js
CHANGED
|
@@ -1,30 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const WABinary_1 = require("../WABinary");
|
|
15
|
-
const socket_1 = require("./socket");
|
|
16
|
-
const WAUSync_1 = require("../WAUSync");
|
|
17
|
-
const usync_1 = require("./usync");
|
|
1
|
+
import NodeCache from '@cacheable/node-cache';
|
|
2
|
+
import { Boom } from '@hapi/boom';
|
|
3
|
+
import { proto } from '../../WAProto/index.js';
|
|
4
|
+
import { DEFAULT_CACHE_TTLS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
|
|
5
|
+
import { ALL_WA_PATCH_NAMES } from '../Types/index.js';
|
|
6
|
+
import { SyncState } from '../Types/State.js';
|
|
7
|
+
import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, extractSyncdPatches, generateProfilePicture, getHistoryMsg, newLTHashState, processSyncAction } from '../Utils/index.js';
|
|
8
|
+
import { makeMutex } from '../Utils/make-mutex.js';
|
|
9
|
+
import processMessage from '../Utils/process-message.js';
|
|
10
|
+
import { buildTcTokenFromJid } from '../Utils/tc-token-utils.js';
|
|
11
|
+
import { getBinaryNodeChild, getBinaryNodeChildren, isLidUser, isPnUser, jidDecode, jidNormalizedUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
12
|
+
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
13
|
+
import { makeSocket } from './socket.js';
|
|
18
14
|
const MAX_SYNC_ATTEMPTS = 2;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const {
|
|
15
|
+
// Lia@Note 08-02-26 --- I know it's not efficient for RSS ಥ‿ಥ
|
|
16
|
+
const USER_ID_CACHE = new Map();
|
|
17
|
+
export const makeChatsSocket = (config) => {
|
|
18
|
+
const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, getMessage } = config;
|
|
19
|
+
const sock = makeSocket(config);
|
|
20
|
+
const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, sendUnifiedSession } = sock;
|
|
23
21
|
let privacySettings;
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
let syncState = SyncState.Connecting;
|
|
23
|
+
/** this mutex ensures that messages are processed in order */
|
|
24
|
+
const messageMutex = makeMutex();
|
|
25
|
+
/** this mutex ensures that receipts are processed in order */
|
|
26
|
+
const receiptMutex = makeMutex();
|
|
27
|
+
/** this mutex ensures that app state patches are processed in order */
|
|
28
|
+
const appStatePatchMutex = makeMutex();
|
|
29
|
+
/** this mutex ensures that notifications are processed in order */
|
|
30
|
+
const notificationMutex = makeMutex();
|
|
31
|
+
// Timeout for AwaitingInitialSync state
|
|
32
|
+
let awaitingSyncTimeout;
|
|
33
|
+
const placeholderResendCache = config.placeholderResendCache ||
|
|
34
|
+
new NodeCache({
|
|
35
|
+
stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
36
|
+
useClones: false
|
|
37
|
+
});
|
|
38
|
+
if (!config.placeholderResendCache) {
|
|
39
|
+
config.placeholderResendCache = placeholderResendCache;
|
|
40
|
+
}
|
|
28
41
|
/** helper function to fetch the given app state sync key */
|
|
29
42
|
const getAppStateSyncKey = async (keyId) => {
|
|
30
43
|
const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId]);
|
|
@@ -36,14 +49,12 @@ const makeChatsSocket = (config) => {
|
|
|
36
49
|
tag: 'iq',
|
|
37
50
|
attrs: {
|
|
38
51
|
xmlns: 'privacy',
|
|
39
|
-
to:
|
|
52
|
+
to: S_WHATSAPP_NET,
|
|
40
53
|
type: 'get'
|
|
41
54
|
},
|
|
42
|
-
content: [
|
|
43
|
-
{ tag: 'privacy', attrs: {} }
|
|
44
|
-
]
|
|
55
|
+
content: [{ tag: 'privacy', attrs: {} }]
|
|
45
56
|
});
|
|
46
|
-
privacySettings =
|
|
57
|
+
privacySettings = reduceBinaryNodeToDictionary(content?.[0], 'category');
|
|
47
58
|
}
|
|
48
59
|
return privacySettings;
|
|
49
60
|
};
|
|
@@ -53,10 +64,11 @@ const makeChatsSocket = (config) => {
|
|
|
53
64
|
tag: 'iq',
|
|
54
65
|
attrs: {
|
|
55
66
|
xmlns: 'privacy',
|
|
56
|
-
to:
|
|
67
|
+
to: S_WHATSAPP_NET,
|
|
57
68
|
type: 'set'
|
|
58
69
|
},
|
|
59
|
-
content: [
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
60
72
|
tag: 'privacy',
|
|
61
73
|
attrs: {},
|
|
62
74
|
content: [
|
|
@@ -65,9 +77,16 @@ const makeChatsSocket = (config) => {
|
|
|
65
77
|
attrs: { name, value }
|
|
66
78
|
}
|
|
67
79
|
]
|
|
68
|
-
}
|
|
80
|
+
}
|
|
81
|
+
]
|
|
69
82
|
});
|
|
70
83
|
};
|
|
84
|
+
const updateMessagesPrivacy = async (value) => {
|
|
85
|
+
await privacyQuery('messages', value);
|
|
86
|
+
};
|
|
87
|
+
const updateCallPrivacy = async (value) => {
|
|
88
|
+
await privacyQuery('calladd', value);
|
|
89
|
+
};
|
|
71
90
|
const updateLastSeenPrivacy = async (value) => {
|
|
72
91
|
await privacyQuery('last', value);
|
|
73
92
|
};
|
|
@@ -86,282 +105,128 @@ const makeChatsSocket = (config) => {
|
|
|
86
105
|
const updateGroupsAddPrivacy = async (value) => {
|
|
87
106
|
await privacyQuery('groupadd', value);
|
|
88
107
|
};
|
|
89
|
-
/** check whether your WhatsApp account is blocked or not */
|
|
90
|
-
const checkWhatsApp = async (jid) => {
|
|
91
|
-
if (!jid) {
|
|
92
|
-
throw new Error('enter jid');
|
|
93
|
-
}
|
|
94
|
-
let resultData = {
|
|
95
|
-
isBanned: false,
|
|
96
|
-
isNeedOfficialWa: false,
|
|
97
|
-
number: jid
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
let phoneNumber = jid;
|
|
101
|
-
if (phoneNumber.includes('@')) {
|
|
102
|
-
phoneNumber = phoneNumber.split('@')[0];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
phoneNumber = phoneNumber.replace(/[^\d+]/g, '');
|
|
106
|
-
if (!phoneNumber.startsWith('+')) {
|
|
107
|
-
if (phoneNumber.startsWith('0')) {
|
|
108
|
-
phoneNumber = phoneNumber.substring(1);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (!phoneNumber.startsWith('62') && phoneNumber.length > 0) {
|
|
112
|
-
phoneNumber = '62' + phoneNumber;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (!phoneNumber.startsWith('+') && phoneNumber.length > 0) {
|
|
116
|
-
phoneNumber = '+' + phoneNumber;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
let formattedNumber = phoneNumber;
|
|
121
|
-
const { parsePhoneNumber } = require('libphonenumber-js');
|
|
122
|
-
const parsedNumber = parsePhoneNumber(formattedNumber);
|
|
123
|
-
const countryCode = parsedNumber.countryCallingCode;
|
|
124
|
-
const nationalNumber = parsedNumber.nationalNumber;
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
const {
|
|
128
|
-
useMultiFileAuthState,
|
|
129
|
-
Browsers,
|
|
130
|
-
fetchLatestBaileysVersion
|
|
131
|
-
} = require('../Utils');
|
|
132
|
-
const { state } = await useMultiFileAuthState(".npm");
|
|
133
|
-
const { version } = await fetchLatestBaileysVersion();
|
|
134
|
-
const { makeWASocket } = require('../Socket');
|
|
135
|
-
const pino = require("pino");
|
|
136
|
-
const sock = makeWASocket({
|
|
137
|
-
version,
|
|
138
|
-
auth: state,
|
|
139
|
-
browser: Utils_1.Browsers("Chrome"),
|
|
140
|
-
logger: pino({
|
|
141
|
-
level: "silent"
|
|
142
|
-
}),
|
|
143
|
-
printQRInTerminal: false,
|
|
144
|
-
});
|
|
145
|
-
const registrationOptions = {
|
|
146
|
-
phoneNumber: formattedNumber,
|
|
147
|
-
phoneNumberCountryCode: countryCode,
|
|
148
|
-
phoneNumberNationalNumber: nationalNumber,
|
|
149
|
-
phoneNumberMobileCountryCode: "510",
|
|
150
|
-
phoneNumberMobileNetworkCode: "10",
|
|
151
|
-
method: "sms",
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
await sock.requestRegistrationCode(registrationOptions);
|
|
155
|
-
if (sock.ws) {
|
|
156
|
-
sock.ws.close();
|
|
157
|
-
}
|
|
158
|
-
return JSON.stringify(resultData, null, 2);
|
|
159
|
-
} catch (err) {
|
|
160
|
-
if (err?.appeal_token) {
|
|
161
|
-
resultData.isBanned = true;
|
|
162
|
-
resultData.data = {
|
|
163
|
-
violation_type: err.violation_type || null,
|
|
164
|
-
in_app_ban_appeal: err.in_app_ban_appeal || null,
|
|
165
|
-
appeal_token: err.appeal_token || null,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
else if (err?.custom_block_screen || err?.reason === 'blocked') {
|
|
169
|
-
resultData.isNeedOfficialWa = true;
|
|
170
|
-
}
|
|
171
|
-
return JSON.stringify(resultData, null, 2);
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
// 60%
|
|
175
|
-
const reqPairing = async (number, count, config) => {
|
|
176
|
-
const { makeSocket } = require("./socket");
|
|
177
|
-
const socket = makeSocket(config);
|
|
178
|
-
const phoneNumber = number.replace(/[^0-9]/g, '');
|
|
179
|
-
for (let i = 0; i < count; i++) {
|
|
180
|
-
const code = await socket.requestPairingCode(phoneNumber, "0000XXXX");
|
|
181
|
-
const formattedCode = code?.match(/.{1,4}/g)?.join('-') || code;
|
|
182
|
-
console.log(`Spam ${i + 1}/${count} | ${formattedCode}`);
|
|
183
|
-
if (i < count - 1) {
|
|
184
|
-
await new Promise(resolve => setTimeout(resolve, 30000));
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
108
|
const updateDefaultDisappearingMode = async (duration) => {
|
|
189
109
|
await query({
|
|
190
110
|
tag: 'iq',
|
|
191
111
|
attrs: {
|
|
192
112
|
xmlns: 'disappearing_mode',
|
|
193
|
-
to:
|
|
113
|
+
to: S_WHATSAPP_NET,
|
|
194
114
|
type: 'set'
|
|
195
115
|
},
|
|
196
|
-
content: [
|
|
116
|
+
content: [
|
|
117
|
+
{
|
|
197
118
|
tag: 'disappearing_mode',
|
|
198
119
|
attrs: {
|
|
199
120
|
duration: duration.toString()
|
|
200
121
|
}
|
|
201
|
-
}
|
|
122
|
+
}
|
|
123
|
+
]
|
|
202
124
|
});
|
|
203
125
|
};
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const result = await query({
|
|
126
|
+
const getBotListV2 = async () => {
|
|
127
|
+
const resp = await query({
|
|
207
128
|
tag: 'iq',
|
|
208
129
|
attrs: {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
130
|
+
xmlns: 'bot',
|
|
131
|
+
to: S_WHATSAPP_NET,
|
|
132
|
+
type: 'get'
|
|
212
133
|
},
|
|
213
134
|
content: [
|
|
214
135
|
{
|
|
215
|
-
tag: '
|
|
136
|
+
tag: 'bot',
|
|
216
137
|
attrs: {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
last: 'true',
|
|
220
|
-
index: '0',
|
|
221
|
-
context: 'interactive',
|
|
222
|
-
},
|
|
223
|
-
content: [
|
|
224
|
-
{
|
|
225
|
-
tag: 'query',
|
|
226
|
-
attrs: {},
|
|
227
|
-
content: [queryNode]
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
tag: 'list',
|
|
231
|
-
attrs: {},
|
|
232
|
-
content: userNodes
|
|
233
|
-
}
|
|
234
|
-
]
|
|
138
|
+
v: '2'
|
|
139
|
+
}
|
|
235
140
|
}
|
|
236
|
-
]
|
|
237
|
-
});
|
|
238
|
-
const usyncNode = (0, WABinary_1.getBinaryNodeChild)(result, 'usync');
|
|
239
|
-
const listNode = (0, WABinary_1.getBinaryNodeChild)(usyncNode, 'list');
|
|
240
|
-
const users = (0, WABinary_1.getBinaryNodeChildren)(listNode, 'user');
|
|
241
|
-
return users;
|
|
242
|
-
};
|
|
243
|
-
const getBusinessProfile = async (jid) => {
|
|
244
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
245
|
-
const results = await query({
|
|
246
|
-
tag: 'iq',
|
|
247
|
-
attrs: {
|
|
248
|
-
to: 's.whatsapp.net',
|
|
249
|
-
xmlns: 'w:biz',
|
|
250
|
-
type: 'get'
|
|
251
|
-
},
|
|
252
|
-
content: [{
|
|
253
|
-
tag: 'business_profile',
|
|
254
|
-
attrs: { v: '244' },
|
|
255
|
-
content: [{
|
|
256
|
-
tag: 'profile',
|
|
257
|
-
attrs: { jid }
|
|
258
|
-
}]
|
|
259
|
-
}]
|
|
141
|
+
]
|
|
260
142
|
});
|
|
261
|
-
const
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const businessHoursConfig = businessHours ?
|
|
271
|
-
(0, WABinary_1.getBinaryNodeChildren)(businessHours, 'business_hours_config') :
|
|
272
|
-
undefined;
|
|
273
|
-
const websiteStr = (_a = website === null || website === void 0 ? void 0 : website.content) === null || _a === void 0 ? void 0 : _a.toString();
|
|
274
|
-
return {
|
|
275
|
-
wid: (_b = profiles.attrs) === null || _b === void 0 ? void 0 : _b.jid,
|
|
276
|
-
address: (_c = address === null || address === void 0 ? void 0 : address.content) === null || _c === void 0 ? void 0 : _c.toString(),
|
|
277
|
-
description: ((_d = description === null || description === void 0 ? void 0 : description.content) === null || _d === void 0 ? void 0 : _d.toString()) || '',
|
|
278
|
-
website: websiteStr ? [websiteStr] : [],
|
|
279
|
-
email: (_e = email === null || email === void 0 ? void 0 : email.content) === null || _e === void 0 ? void 0 : _e.toString(),
|
|
280
|
-
category: (_f = category === null || category === void 0 ? void 0 : category.content) === null || _f === void 0 ? void 0 : _f.toString(),
|
|
281
|
-
'business_hours': {
|
|
282
|
-
timezone: (_g = businessHours === null || businessHours === void 0 ? void 0 : businessHours.attrs) === null || _g === void 0 ? void 0 : _g.timezone,
|
|
283
|
-
'business_config': businessHoursConfig === null || businessHoursConfig === void 0 ? void 0 : businessHoursConfig.map(({ attrs }) => attrs)
|
|
143
|
+
const botNode = getBinaryNodeChild(resp, 'bot');
|
|
144
|
+
const botList = [];
|
|
145
|
+
for (const section of getBinaryNodeChildren(botNode, 'section')) {
|
|
146
|
+
if (section.attrs.type === 'all') {
|
|
147
|
+
for (const bot of getBinaryNodeChildren(section, 'bot')) {
|
|
148
|
+
botList.push({
|
|
149
|
+
jid: bot.attrs.jid,
|
|
150
|
+
personaId: bot.attrs['persona_id']
|
|
151
|
+
});
|
|
284
152
|
}
|
|
285
|
-
}
|
|
153
|
+
}
|
|
286
154
|
}
|
|
155
|
+
return botList;
|
|
287
156
|
};
|
|
288
|
-
const
|
|
289
|
-
const usyncQuery = new
|
|
290
|
-
.withContactProtocol()
|
|
291
|
-
.withLIDProtocol();
|
|
292
|
-
|
|
157
|
+
const fetchStatus = async (...jids) => {
|
|
158
|
+
const usyncQuery = new USyncQuery().withStatusProtocol();
|
|
293
159
|
for (const jid of jids) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
if (results) {
|
|
300
|
-
const verifiedResults = await Promise.all(
|
|
301
|
-
results.list
|
|
302
|
-
.filter((a) => !!a.contact)
|
|
303
|
-
.map(async ({ contact, id, lid }) => {
|
|
304
|
-
try {
|
|
305
|
-
const businessProfile = await getBusinessProfile(id);
|
|
306
|
-
const isBusiness = businessProfile && Object.keys(businessProfile).length > 0;
|
|
307
|
-
if (isBusiness) {
|
|
308
|
-
const { wid, ...businessInfo } = businessProfile;
|
|
309
|
-
|
|
310
|
-
return {
|
|
311
|
-
jid: id,
|
|
312
|
-
exists: true,
|
|
313
|
-
lid: lid,
|
|
314
|
-
status: 'business',
|
|
315
|
-
businessInfo: businessInfo
|
|
316
|
-
};
|
|
317
|
-
} else {
|
|
318
|
-
return {
|
|
319
|
-
jid: id,
|
|
320
|
-
exists: true,
|
|
321
|
-
lid: lid,
|
|
322
|
-
status: 'regular'
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
} catch (error) {
|
|
326
|
-
return {
|
|
327
|
-
jid: id,
|
|
328
|
-
exists: true,
|
|
329
|
-
lid: lid,
|
|
330
|
-
status: error
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
})
|
|
334
|
-
);
|
|
335
|
-
return verifiedResults;
|
|
160
|
+
usyncQuery.withUser(new USyncUser().withId(jid));
|
|
161
|
+
}
|
|
162
|
+
const result = await sock.executeUSyncQuery(usyncQuery);
|
|
163
|
+
if (result) {
|
|
164
|
+
return result.list;
|
|
336
165
|
}
|
|
337
166
|
};
|
|
338
|
-
const
|
|
339
|
-
const
|
|
167
|
+
const fetchDisappearingDuration = async (...jids) => {
|
|
168
|
+
const usyncQuery = new USyncQuery().withDisappearingModeProtocol();
|
|
169
|
+
for (const jid of jids) {
|
|
170
|
+
usyncQuery.withUser(new USyncUser().withId(jid));
|
|
171
|
+
}
|
|
172
|
+
const result = await sock.executeUSyncQuery(usyncQuery);
|
|
340
173
|
if (result) {
|
|
341
|
-
|
|
342
|
-
return {
|
|
343
|
-
status: status === null || status === void 0 ? void 0 : status.content.toString(),
|
|
344
|
-
setAt: new Date(+((status === null || status === void 0 ? void 0 : status.attrs.t) || 0) * 1000)
|
|
345
|
-
};
|
|
174
|
+
return result.list;
|
|
346
175
|
}
|
|
347
176
|
};
|
|
177
|
+
// Lia@Note 06-02-26 --- Quick helper only. This function exists solely for faster lookup with caching.
|
|
178
|
+
const findUserId = async (pnLid) => {
|
|
179
|
+
const cachedId = USER_ID_CACHE.get(pnLid);
|
|
180
|
+
if (cachedId) {
|
|
181
|
+
return cachedId;
|
|
182
|
+
}
|
|
183
|
+
const userId = {};
|
|
184
|
+
if (isPnUser(pnLid)) {
|
|
185
|
+
userId.phoneNumber = pnLid;
|
|
186
|
+
userId.lid = (await signalRepository.lidMapping.getLIDsForPNs([pnLid]))?.[0]?.lid;
|
|
187
|
+
if (!userId.lid) {
|
|
188
|
+
userId.lid = 'id-not-found';
|
|
189
|
+
return userId; // Lia@Note 06-02-26 --- Early return to skip caching for non-existent ID
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else if (isLidUser(pnLid)) {
|
|
193
|
+
userId.lid = pnLid;
|
|
194
|
+
userId.phoneNumber = (await signalRepository.lidMapping.getPNsForLIDs([pnLid]))?.[0]?.pn;
|
|
195
|
+
if (!userId.phoneNumber) {
|
|
196
|
+
userId.phoneNumber = 'id-not-found';
|
|
197
|
+
return userId; // Lia@Note 06-02-26 --- Early return to skip caching for non-existent ID
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
throw new Boom('Invalid id input to find user ids', { statusCode: 400 });
|
|
202
|
+
}
|
|
203
|
+
userId.phoneNumber = jidNormalizedUser(userId.phoneNumber);
|
|
204
|
+
userId.lid = jidNormalizedUser(userId.lid);
|
|
205
|
+
// Lia@Note 06-02-26 --- I know... it's dirty (╯︵╰,)
|
|
206
|
+
USER_ID_CACHE.set(userId.phoneNumber, userId);
|
|
207
|
+
USER_ID_CACHE.set(userId.lid, userId);
|
|
208
|
+
return userId;
|
|
209
|
+
};
|
|
348
210
|
/** update the profile picture for yourself or a group */
|
|
349
|
-
const updateProfilePicture = async (jid, content) => {
|
|
211
|
+
const updateProfilePicture = async (jid, content, dimensions) => {
|
|
350
212
|
let targetJid;
|
|
351
213
|
if (!jid) {
|
|
352
|
-
throw new
|
|
214
|
+
throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update');
|
|
353
215
|
}
|
|
354
|
-
if (
|
|
355
|
-
targetJid =
|
|
216
|
+
if (jidNormalizedUser(jid) !== jidNormalizedUser(authState.creds.me.id)) {
|
|
217
|
+
targetJid = jidNormalizedUser(jid); // in case it is someone other than us
|
|
356
218
|
}
|
|
357
|
-
|
|
219
|
+
else {
|
|
220
|
+
targetJid = undefined;
|
|
221
|
+
}
|
|
222
|
+
const { img } = await generateProfilePicture(content, dimensions);
|
|
358
223
|
await query({
|
|
359
224
|
tag: 'iq',
|
|
360
225
|
attrs: {
|
|
361
|
-
|
|
362
|
-
to: WABinary_1.S_WHATSAPP_NET,
|
|
226
|
+
to: S_WHATSAPP_NET,
|
|
363
227
|
type: 'set',
|
|
364
|
-
xmlns: 'w:profile:picture'
|
|
228
|
+
xmlns: 'w:profile:picture',
|
|
229
|
+
...(targetJid ? { target: targetJid } : {})
|
|
365
230
|
},
|
|
366
231
|
content: [
|
|
367
232
|
{
|
|
@@ -376,18 +241,21 @@ const makeChatsSocket = (config) => {
|
|
|
376
241
|
const removeProfilePicture = async (jid) => {
|
|
377
242
|
let targetJid;
|
|
378
243
|
if (!jid) {
|
|
379
|
-
throw new
|
|
244
|
+
throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update');
|
|
380
245
|
}
|
|
381
|
-
if (
|
|
382
|
-
targetJid =
|
|
246
|
+
if (jidNormalizedUser(jid) !== jidNormalizedUser(authState.creds.me.id)) {
|
|
247
|
+
targetJid = jidNormalizedUser(jid); // in case it is someone other than us
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
targetJid = undefined;
|
|
383
251
|
}
|
|
384
252
|
await query({
|
|
385
253
|
tag: 'iq',
|
|
386
254
|
attrs: {
|
|
387
|
-
|
|
388
|
-
to: WABinary_1.S_WHATSAPP_NET,
|
|
255
|
+
to: S_WHATSAPP_NET,
|
|
389
256
|
type: 'set',
|
|
390
|
-
xmlns: 'w:profile:picture'
|
|
257
|
+
xmlns: 'w:profile:picture',
|
|
258
|
+
...(targetJid ? { target: targetJid } : {})
|
|
391
259
|
}
|
|
392
260
|
});
|
|
393
261
|
};
|
|
@@ -396,7 +264,7 @@ const makeChatsSocket = (config) => {
|
|
|
396
264
|
await query({
|
|
397
265
|
tag: 'iq',
|
|
398
266
|
attrs: {
|
|
399
|
-
to:
|
|
267
|
+
to: S_WHATSAPP_NET,
|
|
400
268
|
type: 'set',
|
|
401
269
|
xmlns: 'status'
|
|
402
270
|
},
|
|
@@ -417,20 +285,19 @@ const makeChatsSocket = (config) => {
|
|
|
417
285
|
tag: 'iq',
|
|
418
286
|
attrs: {
|
|
419
287
|
xmlns: 'blocklist',
|
|
420
|
-
to:
|
|
288
|
+
to: S_WHATSAPP_NET,
|
|
421
289
|
type: 'get'
|
|
422
290
|
}
|
|
423
291
|
});
|
|
424
|
-
const listNode =
|
|
425
|
-
return
|
|
426
|
-
.map(n => n.attrs.jid);
|
|
292
|
+
const listNode = getBinaryNodeChild(result, 'list');
|
|
293
|
+
return getBinaryNodeChildren(listNode, 'item').map(n => n.attrs.jid);
|
|
427
294
|
};
|
|
428
295
|
const updateBlockStatus = async (jid, action) => {
|
|
429
296
|
await query({
|
|
430
297
|
tag: 'iq',
|
|
431
298
|
attrs: {
|
|
432
299
|
xmlns: 'blocklist',
|
|
433
|
-
to:
|
|
300
|
+
to: S_WHATSAPP_NET,
|
|
434
301
|
type: 'set'
|
|
435
302
|
},
|
|
436
303
|
content: [
|
|
@@ -444,22 +311,70 @@ const makeChatsSocket = (config) => {
|
|
|
444
311
|
]
|
|
445
312
|
});
|
|
446
313
|
};
|
|
314
|
+
const getBusinessProfile = async (jid) => {
|
|
315
|
+
const results = await query({
|
|
316
|
+
tag: 'iq',
|
|
317
|
+
attrs: {
|
|
318
|
+
to: 's.whatsapp.net',
|
|
319
|
+
xmlns: 'w:biz',
|
|
320
|
+
type: 'get'
|
|
321
|
+
},
|
|
322
|
+
content: [
|
|
323
|
+
{
|
|
324
|
+
tag: 'business_profile',
|
|
325
|
+
attrs: { v: '244' },
|
|
326
|
+
content: [
|
|
327
|
+
{
|
|
328
|
+
tag: 'profile',
|
|
329
|
+
attrs: { jid }
|
|
330
|
+
}
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
]
|
|
334
|
+
});
|
|
335
|
+
const profileNode = getBinaryNodeChild(results, 'business_profile');
|
|
336
|
+
const profiles = getBinaryNodeChild(profileNode, 'profile');
|
|
337
|
+
if (profiles) {
|
|
338
|
+
const address = getBinaryNodeChild(profiles, 'address');
|
|
339
|
+
const description = getBinaryNodeChild(profiles, 'description');
|
|
340
|
+
const website = getBinaryNodeChild(profiles, 'website');
|
|
341
|
+
const email = getBinaryNodeChild(profiles, 'email');
|
|
342
|
+
const category = getBinaryNodeChild(getBinaryNodeChild(profiles, 'categories'), 'category');
|
|
343
|
+
const businessHours = getBinaryNodeChild(profiles, 'business_hours');
|
|
344
|
+
const businessHoursConfig = businessHours
|
|
345
|
+
? getBinaryNodeChildren(businessHours, 'business_hours_config')
|
|
346
|
+
: undefined;
|
|
347
|
+
const websiteStr = website?.content?.toString();
|
|
348
|
+
return {
|
|
349
|
+
wid: profiles.attrs?.jid,
|
|
350
|
+
address: address?.content?.toString(),
|
|
351
|
+
description: description?.content?.toString() || '',
|
|
352
|
+
website: websiteStr ? [websiteStr] : [],
|
|
353
|
+
email: email?.content?.toString(),
|
|
354
|
+
category: category?.content?.toString(),
|
|
355
|
+
business_hours: {
|
|
356
|
+
timezone: businessHours?.attrs?.timezone,
|
|
357
|
+
business_config: businessHoursConfig?.map(({ attrs }) => attrs)
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
};
|
|
447
362
|
const cleanDirtyBits = async (type, fromTimestamp) => {
|
|
448
363
|
logger.info({ fromTimestamp }, 'clean dirty bits ' + type);
|
|
449
364
|
await sendNode({
|
|
450
365
|
tag: 'iq',
|
|
451
366
|
attrs: {
|
|
452
|
-
to:
|
|
367
|
+
to: S_WHATSAPP_NET,
|
|
453
368
|
type: 'set',
|
|
454
369
|
xmlns: 'urn:xmpp:whatsapp:dirty',
|
|
455
|
-
id: generateMessageTag()
|
|
370
|
+
id: generateMessageTag()
|
|
456
371
|
},
|
|
457
372
|
content: [
|
|
458
373
|
{
|
|
459
374
|
tag: 'clean',
|
|
460
375
|
attrs: {
|
|
461
376
|
type,
|
|
462
|
-
...(fromTimestamp ? { timestamp: fromTimestamp.toString() } : null)
|
|
377
|
+
...(fromTimestamp ? { timestamp: fromTimestamp.toString() } : null)
|
|
463
378
|
}
|
|
464
379
|
}
|
|
465
380
|
]
|
|
@@ -468,26 +383,25 @@ const makeChatsSocket = (config) => {
|
|
|
468
383
|
const newAppStateChunkHandler = (isInitialSync) => {
|
|
469
384
|
return {
|
|
470
385
|
onMutation(mutation) {
|
|
471
|
-
|
|
386
|
+
processSyncAction(mutation, ev, authState.creds.me, isInitialSync ? { accountSettings: authState.creds.accountSettings } : undefined, logger);
|
|
472
387
|
}
|
|
473
388
|
};
|
|
474
389
|
};
|
|
475
|
-
// Buffered version — used for initial sync only (holds events until sync completes)
|
|
476
390
|
const resyncAppState = ev.createBufferedFunction(async (collections, isInitialSync) => {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
391
|
+
const appStateSyncKeyCache = new Map();
|
|
392
|
+
const getCachedAppStateSyncKey = async (keyId) => {
|
|
393
|
+
if (appStateSyncKeyCache.has(keyId)) {
|
|
394
|
+
return appStateSyncKeyCache.get(keyId) ?? undefined;
|
|
395
|
+
}
|
|
396
|
+
const key = await getAppStateSyncKey(keyId);
|
|
397
|
+
appStateSyncKeyCache.set(keyId, key ?? null);
|
|
398
|
+
return key;
|
|
399
|
+
};
|
|
485
400
|
// we use this to determine which events to fire
|
|
486
401
|
// otherwise when we resync from scratch -- all notifications will fire
|
|
487
402
|
const initialVersionMap = {};
|
|
488
403
|
const globalMutationMap = {};
|
|
489
404
|
await authState.keys.transaction(async () => {
|
|
490
|
-
var _a;
|
|
491
405
|
const collectionsToHandle = new Set(collections);
|
|
492
406
|
// in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
|
|
493
407
|
const attemptsMap = {};
|
|
@@ -506,7 +420,7 @@ const makeChatsSocket = (config) => {
|
|
|
506
420
|
}
|
|
507
421
|
}
|
|
508
422
|
else {
|
|
509
|
-
state =
|
|
423
|
+
state = newLTHashState();
|
|
510
424
|
}
|
|
511
425
|
states[name] = state;
|
|
512
426
|
logger.info(`resyncing ${name} from v${state.version}`);
|
|
@@ -516,14 +430,14 @@ const makeChatsSocket = (config) => {
|
|
|
516
430
|
name,
|
|
517
431
|
version: state.version.toString(),
|
|
518
432
|
// return snapshot if being synced from scratch
|
|
519
|
-
|
|
433
|
+
return_snapshot: (!state.version).toString()
|
|
520
434
|
}
|
|
521
435
|
});
|
|
522
436
|
}
|
|
523
437
|
const result = await query({
|
|
524
438
|
tag: 'iq',
|
|
525
439
|
attrs: {
|
|
526
|
-
to:
|
|
440
|
+
to: S_WHATSAPP_NET,
|
|
527
441
|
xmlns: 'w:sync:app:state',
|
|
528
442
|
type: 'set'
|
|
529
443
|
},
|
|
@@ -536,26 +450,22 @@ const makeChatsSocket = (config) => {
|
|
|
536
450
|
]
|
|
537
451
|
});
|
|
538
452
|
// extract from binary node
|
|
539
|
-
const decoded = await
|
|
453
|
+
const decoded = await extractSyncdPatches(result, config?.options);
|
|
540
454
|
for (const key in decoded) {
|
|
541
455
|
const name = key;
|
|
542
456
|
const { patches, hasMorePatches, snapshot } = decoded[name];
|
|
543
457
|
try {
|
|
544
458
|
if (snapshot) {
|
|
545
|
-
const { state: newState, mutationMap } = await
|
|
459
|
+
const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot, getCachedAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot);
|
|
546
460
|
states[name] = newState;
|
|
547
461
|
Object.assign(globalMutationMap, mutationMap);
|
|
548
462
|
logger.info(`restored state of ${name} from snapshot to v${newState.version} with mutations`);
|
|
549
|
-
await authState.keys.set({ 'app-state-sync-version': {
|
|
550
|
-
[name]: newState
|
|
551
|
-
} });
|
|
463
|
+
await authState.keys.set({ 'app-state-sync-version': { [name]: newState } });
|
|
552
464
|
}
|
|
553
465
|
// only process if there are syncd patches
|
|
554
466
|
if (patches.length) {
|
|
555
|
-
const { state: newState, mutationMap } = await
|
|
556
|
-
await authState.keys.set({ 'app-state-sync-version': {
|
|
557
|
-
[name]: newState
|
|
558
|
-
} });
|
|
467
|
+
const { state: newState, mutationMap } = await decodePatches(name, patches, states[name], getCachedAppStateSyncKey, config.options, initialVersionMap[name], logger, appStateMacVerification.patch);
|
|
468
|
+
await authState.keys.set({ 'app-state-sync-version': { [name]: newState } });
|
|
559
469
|
logger.info(`synced ${name} to v${newState.version}`);
|
|
560
470
|
initialVersionMap[name] = newState.version;
|
|
561
471
|
Object.assign(globalMutationMap, mutationMap);
|
|
@@ -563,7 +473,8 @@ const makeChatsSocket = (config) => {
|
|
|
563
473
|
if (hasMorePatches) {
|
|
564
474
|
logger.info(`${name} has more patches...`);
|
|
565
475
|
}
|
|
566
|
-
else {
|
|
476
|
+
else {
|
|
477
|
+
// collection is done with sync
|
|
567
478
|
collectionsToHandle.delete(name);
|
|
568
479
|
}
|
|
569
480
|
}
|
|
@@ -571,12 +482,10 @@ const makeChatsSocket = (config) => {
|
|
|
571
482
|
// if retry attempts overshoot
|
|
572
483
|
// or key not found
|
|
573
484
|
const isIrrecoverableError = attemptsMap[name] >= MAX_SYNC_ATTEMPTS ||
|
|
574
|
-
|
|
485
|
+
error.output?.statusCode === 404 ||
|
|
575
486
|
error.name === 'TypeError';
|
|
576
487
|
logger.info({ name, error: error.stack }, `failed to sync state from version${isIrrecoverableError ? '' : ', removing and trying from scratch'}`);
|
|
577
|
-
await authState.keys.set({ 'app-state-sync-version': {
|
|
578
|
-
[name]: null
|
|
579
|
-
} });
|
|
488
|
+
await authState.keys.set({ 'app-state-sync-version': { [name]: null } });
|
|
580
489
|
// increment number of retries
|
|
581
490
|
attemptsMap[name] = (attemptsMap[name] || 0) + 1;
|
|
582
491
|
if (isIrrecoverableError) {
|
|
@@ -586,59 +495,102 @@ const makeChatsSocket = (config) => {
|
|
|
586
495
|
}
|
|
587
496
|
}
|
|
588
497
|
}
|
|
589
|
-
});
|
|
498
|
+
}, authState?.creds?.me?.id || 'resync-app-state');
|
|
590
499
|
const { onMutation } = newAppStateChunkHandler(isInitialSync);
|
|
591
500
|
for (const key in globalMutationMap) {
|
|
592
501
|
onMutation(globalMutationMap[key]);
|
|
593
502
|
}
|
|
594
|
-
}
|
|
503
|
+
});
|
|
595
504
|
/**
|
|
596
505
|
* fetch the profile picture of a user/group
|
|
597
506
|
* type = "preview" for a low res picture
|
|
598
507
|
* type = "image for the high res picture"
|
|
599
508
|
*/
|
|
600
|
-
const profilePictureUrl = async (jid, type = '
|
|
601
|
-
|
|
602
|
-
jid =
|
|
509
|
+
const profilePictureUrl = async (jid, type = 'image', timeoutMs) => {
|
|
510
|
+
// vltcs@changes 06-02-26 --- Refactor profilePictureUrl() to use tctoken and adjust error handling
|
|
511
|
+
jid = jidNormalizedUser(jid);
|
|
512
|
+
const baseContent = {
|
|
513
|
+
tag: 'picture',
|
|
514
|
+
attrs: {
|
|
515
|
+
type,
|
|
516
|
+
query: 'url'
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
const tcTokenData = await authState.keys.get('tctoken', [jid]);
|
|
520
|
+
const tcTokenBuffer = tcTokenData?.[jid]?.token
|
|
521
|
+
if (tcTokenBuffer) {
|
|
522
|
+
baseContent.content = [{
|
|
523
|
+
tag: 'tctoken',
|
|
524
|
+
attrs: {},
|
|
525
|
+
content: tcTokenBuffer
|
|
526
|
+
}];
|
|
527
|
+
}
|
|
603
528
|
const result = await query({
|
|
604
529
|
tag: 'iq',
|
|
605
530
|
attrs: {
|
|
606
531
|
target: jid,
|
|
607
|
-
to:
|
|
532
|
+
to: S_WHATSAPP_NET,
|
|
608
533
|
type: 'get',
|
|
609
534
|
xmlns: 'w:profile:picture'
|
|
610
535
|
},
|
|
536
|
+
content: [baseContent]
|
|
537
|
+
}, timeoutMs);
|
|
538
|
+
const child = getBinaryNodeChild(result, 'picture');
|
|
539
|
+
if (!child) {
|
|
540
|
+
throw new Boom('Picture node missing', { statusCode: 404 });
|
|
541
|
+
}
|
|
542
|
+
const status = child.attrs?.status;
|
|
543
|
+
if (status === '404' || status === '204') {
|
|
544
|
+
throw new Boom('Profile picture not set', { statusCode: 404 });
|
|
545
|
+
}
|
|
546
|
+
return child?.attrs?.url;
|
|
547
|
+
};
|
|
548
|
+
const createCallLink = async (type, event, timeoutMs) => {
|
|
549
|
+
const result = await query({
|
|
550
|
+
tag: 'call',
|
|
551
|
+
attrs: {
|
|
552
|
+
id: generateMessageTag(),
|
|
553
|
+
to: '@call'
|
|
554
|
+
},
|
|
611
555
|
content: [
|
|
612
|
-
{
|
|
556
|
+
{
|
|
557
|
+
tag: 'link_create',
|
|
558
|
+
attrs: { media: type },
|
|
559
|
+
content: event ? [{ tag: 'event', attrs: { start_time: String(event.startTime) } }] : undefined
|
|
560
|
+
}
|
|
613
561
|
]
|
|
614
562
|
}, timeoutMs);
|
|
615
|
-
const child =
|
|
616
|
-
return
|
|
563
|
+
const child = getBinaryNodeChild(result, 'link_create');
|
|
564
|
+
return child?.attrs?.token;
|
|
617
565
|
};
|
|
618
566
|
const sendPresenceUpdate = async (type, toJid) => {
|
|
619
567
|
const me = authState.creds.me;
|
|
620
|
-
|
|
568
|
+
const isAvailableType = type === 'available';
|
|
569
|
+
if (isAvailableType || type === 'unavailable') {
|
|
621
570
|
if (!me.name) {
|
|
622
571
|
logger.warn('no name present, ignoring presence update request...');
|
|
623
572
|
return;
|
|
624
573
|
}
|
|
625
|
-
ev.emit('connection.update', { isOnline:
|
|
574
|
+
ev.emit('connection.update', { isOnline: isAvailableType });
|
|
575
|
+
if (isAvailableType) {
|
|
576
|
+
void sendUnifiedSession();
|
|
577
|
+
}
|
|
626
578
|
await sendNode({
|
|
627
579
|
tag: 'presence',
|
|
628
580
|
attrs: {
|
|
629
|
-
name: me.name,
|
|
581
|
+
name: me.name.replace(/@/g, ''),
|
|
630
582
|
type
|
|
631
583
|
}
|
|
632
584
|
});
|
|
633
585
|
}
|
|
634
586
|
else {
|
|
635
|
-
const { server } =
|
|
587
|
+
const { server } = jidDecode(toJid);
|
|
636
588
|
const isLid = server === 'lid';
|
|
637
589
|
await sendNode({
|
|
638
590
|
tag: 'chatstate',
|
|
639
591
|
attrs: {
|
|
640
592
|
from: isLid ? me.lid : me.id,
|
|
641
|
-
to: toJid
|
|
593
|
+
to: toJid
|
|
642
594
|
},
|
|
643
595
|
content: [
|
|
644
596
|
{
|
|
@@ -653,29 +605,23 @@ const makeChatsSocket = (config) => {
|
|
|
653
605
|
* @param toJid the jid to subscribe to
|
|
654
606
|
* @param tcToken token for subscription, use if present
|
|
655
607
|
*/
|
|
656
|
-
const presenceSubscribe = (toJid
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
content: tcToken
|
|
669
|
-
}
|
|
670
|
-
] :
|
|
671
|
-
undefined
|
|
672
|
-
}));
|
|
608
|
+
const presenceSubscribe = async (toJid) => {
|
|
609
|
+
const tcTokenContent = await buildTcTokenFromJid({ authState, jid: toJid });
|
|
610
|
+
return sendNode({
|
|
611
|
+
tag: 'presence',
|
|
612
|
+
attrs: {
|
|
613
|
+
to: toJid,
|
|
614
|
+
id: generateMessageTag(),
|
|
615
|
+
type: 'subscribe'
|
|
616
|
+
},
|
|
617
|
+
content: tcTokenContent
|
|
618
|
+
});
|
|
619
|
+
};
|
|
673
620
|
const handlePresenceUpdate = ({ tag, attrs, content }) => {
|
|
674
|
-
var _a;
|
|
675
621
|
let presence;
|
|
676
622
|
const jid = attrs.from;
|
|
677
623
|
const participant = attrs.participant || attrs.from;
|
|
678
|
-
if (shouldIgnoreJid(jid) && jid !==
|
|
624
|
+
if (shouldIgnoreJid(jid) && jid !== S_WHATSAPP_NET) {
|
|
679
625
|
return;
|
|
680
626
|
}
|
|
681
627
|
if (tag === 'presence') {
|
|
@@ -690,7 +636,7 @@ const makeChatsSocket = (config) => {
|
|
|
690
636
|
if (type === 'paused') {
|
|
691
637
|
type = 'available';
|
|
692
638
|
}
|
|
693
|
-
if (
|
|
639
|
+
if (firstChild.attrs?.media === 'audio') {
|
|
694
640
|
type = 'recording';
|
|
695
641
|
}
|
|
696
642
|
presence = { lastKnownPresence: type };
|
|
@@ -699,31 +645,29 @@ const makeChatsSocket = (config) => {
|
|
|
699
645
|
logger.error({ tag, attrs, content }, 'recv invalid presence node');
|
|
700
646
|
}
|
|
701
647
|
if (presence) {
|
|
702
|
-
ev.emit('presence.update', { id: jid, presences: {
|
|
703
|
-
[participant]: presence
|
|
704
|
-
} });
|
|
648
|
+
ev.emit('presence.update', { id: jid, presences: { [participant]: presence } });
|
|
705
649
|
}
|
|
706
650
|
};
|
|
707
651
|
const appPatch = async (patchCreate) => {
|
|
708
652
|
const name = patchCreate.type;
|
|
709
653
|
const myAppStateKeyId = authState.creds.myAppStateKeyId;
|
|
710
654
|
if (!myAppStateKeyId) {
|
|
711
|
-
throw new
|
|
655
|
+
throw new Boom('App state key not present!', { statusCode: 400 });
|
|
712
656
|
}
|
|
713
657
|
let initial;
|
|
714
658
|
let encodeResult;
|
|
715
|
-
await
|
|
659
|
+
await appStatePatchMutex.mutex(async () => {
|
|
716
660
|
await authState.keys.transaction(async () => {
|
|
717
661
|
logger.debug({ patch: patchCreate }, 'applying app patch');
|
|
718
662
|
await resyncAppState([name], false);
|
|
719
663
|
const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name]);
|
|
720
|
-
initial = currentSyncVersion ||
|
|
721
|
-
encodeResult = await
|
|
664
|
+
initial = currentSyncVersion || newLTHashState();
|
|
665
|
+
encodeResult = await encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
|
|
722
666
|
const { patch, state } = encodeResult;
|
|
723
667
|
const node = {
|
|
724
668
|
tag: 'iq',
|
|
725
669
|
attrs: {
|
|
726
|
-
to:
|
|
670
|
+
to: S_WHATSAPP_NET,
|
|
727
671
|
type: 'set',
|
|
728
672
|
xmlns: 'w:sync:app:state'
|
|
729
673
|
},
|
|
@@ -737,13 +681,13 @@ const makeChatsSocket = (config) => {
|
|
|
737
681
|
attrs: {
|
|
738
682
|
name,
|
|
739
683
|
version: (state.version - 1).toString(),
|
|
740
|
-
|
|
684
|
+
return_snapshot: 'false'
|
|
741
685
|
},
|
|
742
686
|
content: [
|
|
743
687
|
{
|
|
744
688
|
tag: 'patch',
|
|
745
689
|
attrs: {},
|
|
746
|
-
content:
|
|
690
|
+
content: proto.SyncdPatch.encode(patch).finish()
|
|
747
691
|
}
|
|
748
692
|
]
|
|
749
693
|
}
|
|
@@ -752,14 +696,12 @@ const makeChatsSocket = (config) => {
|
|
|
752
696
|
]
|
|
753
697
|
};
|
|
754
698
|
await query(node);
|
|
755
|
-
await authState.keys.set({ 'app-state-sync-version': {
|
|
756
|
-
|
|
757
|
-
} });
|
|
758
|
-
});
|
|
699
|
+
await authState.keys.set({ 'app-state-sync-version': { [name]: state } });
|
|
700
|
+
}, authState?.creds?.me?.id || 'app-patch');
|
|
759
701
|
});
|
|
760
702
|
if (config.emitOwnEvents) {
|
|
761
703
|
const { onMutation } = newAppStateChunkHandler(false);
|
|
762
|
-
const { mutationMap } = await
|
|
704
|
+
const { mutationMap } = await decodePatches(name, [{ ...encodeResult.patch, version: { version: encodeResult.state.version } }], initial, getAppStateSyncKey, config.options, undefined, logger);
|
|
763
705
|
for (const key in mutationMap) {
|
|
764
706
|
onMutation(mutationMap[key]);
|
|
765
707
|
}
|
|
@@ -767,30 +709,33 @@ const makeChatsSocket = (config) => {
|
|
|
767
709
|
};
|
|
768
710
|
/** sending non-abt props may fix QR scan fail if server expects */
|
|
769
711
|
const fetchProps = async () => {
|
|
770
|
-
|
|
712
|
+
//TODO: implement both protocol 1 and protocol 2 prop fetching, specially for abKey for WM
|
|
771
713
|
const resultNode = await query({
|
|
772
714
|
tag: 'iq',
|
|
773
715
|
attrs: {
|
|
774
|
-
to:
|
|
716
|
+
to: S_WHATSAPP_NET,
|
|
775
717
|
xmlns: 'w',
|
|
776
|
-
type: 'get'
|
|
718
|
+
type: 'get'
|
|
777
719
|
},
|
|
778
720
|
content: [
|
|
779
721
|
{
|
|
780
722
|
tag: 'props',
|
|
781
723
|
attrs: {
|
|
782
724
|
protocol: '2',
|
|
783
|
-
hash:
|
|
725
|
+
hash: authState?.creds?.lastPropHash || ''
|
|
784
726
|
}
|
|
785
727
|
}
|
|
786
728
|
]
|
|
787
729
|
});
|
|
788
|
-
const propsNode =
|
|
730
|
+
const propsNode = getBinaryNodeChild(resultNode, 'props');
|
|
789
731
|
let props = {};
|
|
790
732
|
if (propsNode) {
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
733
|
+
if (propsNode.attrs?.hash) {
|
|
734
|
+
// on some clients, the hash is returning as undefined
|
|
735
|
+
authState.creds.lastPropHash = propsNode?.attrs?.hash;
|
|
736
|
+
ev.emit('creds.update', authState.creds);
|
|
737
|
+
}
|
|
738
|
+
props = reduceBinaryNodeToDictionary(propsNode, 'prop');
|
|
794
739
|
}
|
|
795
740
|
logger.debug('fetched props');
|
|
796
741
|
return props;
|
|
@@ -801,9 +746,17 @@ const makeChatsSocket = (config) => {
|
|
|
801
746
|
* requires the last messages till the last message received; required for archive & unread
|
|
802
747
|
*/
|
|
803
748
|
const chatModify = (mod, jid) => {
|
|
804
|
-
const patch =
|
|
749
|
+
const patch = chatModificationToAppPatch(mod, jid);
|
|
805
750
|
return appPatch(patch);
|
|
806
751
|
};
|
|
752
|
+
/**
|
|
753
|
+
* Enable/Disable link preview privacy, not related to baileys link preview generation
|
|
754
|
+
*/
|
|
755
|
+
const updateDisableLinkPreviewsPrivacy = (isPreviewsDisabled) => {
|
|
756
|
+
return chatModify({
|
|
757
|
+
disableLinkPreviews: { isPreviewsDisabled }
|
|
758
|
+
}, '');
|
|
759
|
+
};
|
|
807
760
|
/**
|
|
808
761
|
* Star or Unstar a message
|
|
809
762
|
*/
|
|
@@ -815,6 +768,32 @@ const makeChatsSocket = (config) => {
|
|
|
815
768
|
}
|
|
816
769
|
}, jid);
|
|
817
770
|
};
|
|
771
|
+
/**
|
|
772
|
+
* Add or Edit Contact
|
|
773
|
+
*/
|
|
774
|
+
const addOrEditContact = (jid, contact) => {
|
|
775
|
+
return chatModify({
|
|
776
|
+
contact
|
|
777
|
+
}, jid);
|
|
778
|
+
};
|
|
779
|
+
/**
|
|
780
|
+
* Remove Contact
|
|
781
|
+
*/
|
|
782
|
+
const removeContact = (jid) => {
|
|
783
|
+
return chatModify({
|
|
784
|
+
contact: null
|
|
785
|
+
}, jid);
|
|
786
|
+
};
|
|
787
|
+
/**
|
|
788
|
+
* Adds label
|
|
789
|
+
*/
|
|
790
|
+
const addLabel = (jid, labels) => {
|
|
791
|
+
return chatModify({
|
|
792
|
+
addLabel: {
|
|
793
|
+
...labels
|
|
794
|
+
}
|
|
795
|
+
}, jid);
|
|
796
|
+
};
|
|
818
797
|
/**
|
|
819
798
|
* Adds label for the chats
|
|
820
799
|
*/
|
|
@@ -857,82 +836,104 @@ const makeChatsSocket = (config) => {
|
|
|
857
836
|
}
|
|
858
837
|
}, jid);
|
|
859
838
|
};
|
|
839
|
+
/**
|
|
840
|
+
* Add or Edit Quick Reply
|
|
841
|
+
*/
|
|
842
|
+
const addOrEditQuickReply = (quickReply) => {
|
|
843
|
+
return chatModify({
|
|
844
|
+
quickReply
|
|
845
|
+
}, '');
|
|
846
|
+
};
|
|
847
|
+
/**
|
|
848
|
+
* Remove Quick Reply
|
|
849
|
+
*/
|
|
850
|
+
const removeQuickReply = (timestamp) => {
|
|
851
|
+
return chatModify({
|
|
852
|
+
quickReply: { timestamp, deleted: true }
|
|
853
|
+
}, '');
|
|
854
|
+
};
|
|
860
855
|
/**
|
|
861
856
|
* queries need to be fired on connection open
|
|
862
857
|
* help ensure parity with WA Web
|
|
863
858
|
* */
|
|
864
859
|
const executeInitQueries = async () => {
|
|
865
|
-
await Promise.all([
|
|
866
|
-
fetchProps(),
|
|
867
|
-
fetchBlocklist(),
|
|
868
|
-
fetchPrivacySettings(),
|
|
869
|
-
]);
|
|
860
|
+
await Promise.all([fetchProps(), fetchBlocklist(), fetchPrivacySettings()]);
|
|
870
861
|
};
|
|
871
862
|
const upsertMessage = ev.createBufferedFunction(async (msg, type) => {
|
|
872
|
-
var _a, _b, _c;
|
|
873
863
|
ev.emit('messages.upsert', { messages: [msg], type });
|
|
874
864
|
if (!!msg.pushName) {
|
|
875
|
-
let jid = msg.key.fromMe ? authState.creds.me.id :
|
|
876
|
-
jid =
|
|
865
|
+
let jid = msg.key.fromMe ? authState.creds.me.id : msg.key.participant || msg.key.remoteJid;
|
|
866
|
+
jid = jidNormalizedUser(jid);
|
|
877
867
|
if (!msg.key.fromMe) {
|
|
878
868
|
ev.emit('contacts.update', [{ id: jid, notify: msg.pushName, verifiedName: msg.verifiedBizName }]);
|
|
879
869
|
}
|
|
880
870
|
// update our pushname too
|
|
881
|
-
if (msg.key.fromMe && msg.pushName &&
|
|
871
|
+
if (msg.key.fromMe && msg.pushName && authState.creds.me?.name !== msg.pushName) {
|
|
882
872
|
ev.emit('creds.update', { me: { ...authState.creds.me, name: msg.pushName } });
|
|
883
873
|
}
|
|
884
874
|
}
|
|
885
|
-
const historyMsg =
|
|
886
|
-
const shouldProcessHistoryMsg = historyMsg
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
false;
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
// are not delayed while the potentially large state sync runs on reconnect
|
|
896
|
-
const appStateSyncPromise = (async () => {
|
|
897
|
-
if (historyMsg && authState.creds.myAppStateKeyId) {
|
|
898
|
-
pendingAppStateSync = false;
|
|
899
|
-
await doAppStateSync();
|
|
875
|
+
const historyMsg = getHistoryMsg(msg.message);
|
|
876
|
+
const shouldProcessHistoryMsg = historyMsg
|
|
877
|
+
? shouldSyncHistoryMessage(historyMsg) &&
|
|
878
|
+
PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType)
|
|
879
|
+
: false;
|
|
880
|
+
// State machine: decide on sync and flush
|
|
881
|
+
if (historyMsg && syncState === SyncState.AwaitingInitialSync) {
|
|
882
|
+
if (awaitingSyncTimeout) {
|
|
883
|
+
clearTimeout(awaitingSyncTimeout);
|
|
884
|
+
awaitingSyncTimeout = undefined;
|
|
900
885
|
}
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
if (!authState.creds.accountSyncCounter) {
|
|
921
|
-
logger.info('doing initial app state sync');
|
|
922
|
-
await resyncAppState(Types_1.ALL_WA_PATCH_NAMES, true);
|
|
886
|
+
if (shouldProcessHistoryMsg) {
|
|
887
|
+
syncState = SyncState.Syncing;
|
|
888
|
+
logger.info('Transitioned to Syncing state');
|
|
889
|
+
// Let doAppStateSync handle the final flush after it's done
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
syncState = SyncState.Online;
|
|
893
|
+
logger.info('History sync skipped, transitioning to Online state and flushing buffer');
|
|
894
|
+
ev.flush();
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
const doAppStateSync = async () => {
|
|
898
|
+
if (syncState === SyncState.Syncing) {
|
|
899
|
+
logger.info('Doing app state sync');
|
|
900
|
+
await resyncAppState(ALL_WA_PATCH_NAMES, true);
|
|
901
|
+
// Sync is complete, go online and flush everything
|
|
902
|
+
syncState = SyncState.Online;
|
|
903
|
+
logger.info('App state sync complete, transitioning to Online state and flushing buffer');
|
|
904
|
+
ev.flush();
|
|
923
905
|
const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
|
|
924
906
|
ev.emit('creds.update', { accountSyncCounter });
|
|
925
|
-
if (needToFlushWithAppStateSync) {
|
|
926
|
-
logger.debug('flushing with app state sync');
|
|
927
|
-
ev.flush();
|
|
928
|
-
}
|
|
929
907
|
}
|
|
908
|
+
};
|
|
909
|
+
await Promise.all([
|
|
910
|
+
(async () => {
|
|
911
|
+
if (shouldProcessHistoryMsg) {
|
|
912
|
+
await doAppStateSync();
|
|
913
|
+
}
|
|
914
|
+
})(),
|
|
915
|
+
processMessage(msg, {
|
|
916
|
+
signalRepository,
|
|
917
|
+
shouldProcessHistoryMsg,
|
|
918
|
+
placeholderResendCache,
|
|
919
|
+
ev,
|
|
920
|
+
creds: authState.creds,
|
|
921
|
+
keyStore: authState.keys,
|
|
922
|
+
logger,
|
|
923
|
+
options: config.options,
|
|
924
|
+
getMessage
|
|
925
|
+
})
|
|
926
|
+
]);
|
|
927
|
+
// If the app state key arrives and we are waiting to sync, trigger the sync now.
|
|
928
|
+
if (msg.message?.protocolMessage?.appStateSyncKeyShare && syncState === SyncState.Syncing) {
|
|
929
|
+
logger.info('App state sync key arrived, triggering app state sync');
|
|
930
|
+
await doAppStateSync();
|
|
930
931
|
}
|
|
931
932
|
});
|
|
932
933
|
ws.on('CB:presence', handlePresenceUpdate);
|
|
933
934
|
ws.on('CB:chatstate', handlePresenceUpdate);
|
|
934
935
|
ws.on('CB:ib,,dirty', async (node) => {
|
|
935
|
-
const { attrs } =
|
|
936
|
+
const { attrs } = getBinaryNodeChild(node, 'dirty');
|
|
936
937
|
const type = attrs.type;
|
|
937
938
|
switch (type) {
|
|
938
939
|
case 'account_sync':
|
|
@@ -954,42 +955,74 @@ const makeChatsSocket = (config) => {
|
|
|
954
955
|
}
|
|
955
956
|
});
|
|
956
957
|
ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
|
|
957
|
-
var _a;
|
|
958
958
|
if (connection === 'open') {
|
|
959
959
|
if (fireInitQueries) {
|
|
960
|
-
executeInitQueries()
|
|
961
|
-
.catch(error => onUnexpectedError(error, 'init queries'));
|
|
960
|
+
executeInitQueries().catch(error => onUnexpectedError(error, 'init queries'));
|
|
962
961
|
}
|
|
963
|
-
sendPresenceUpdate(markOnlineOnConnect ? 'available' : 'unavailable')
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
962
|
+
sendPresenceUpdate(markOnlineOnConnect ? 'available' : 'unavailable').catch(error => onUnexpectedError(error, 'presence update requests'));
|
|
963
|
+
}
|
|
964
|
+
if (!receivedPendingNotifications || syncState !== SyncState.Connecting) {
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
syncState = SyncState.AwaitingInitialSync;
|
|
968
|
+
logger.info('Connection is now AwaitingInitialSync, buffering events');
|
|
969
|
+
ev.buffer();
|
|
970
|
+
const willSyncHistory = shouldSyncHistoryMessage(proto.Message.HistorySyncNotification.create({
|
|
971
|
+
syncType: proto.HistorySync.HistorySyncType.RECENT
|
|
972
|
+
}));
|
|
973
|
+
if (!willSyncHistory) {
|
|
974
|
+
logger.info('History sync is disabled by config, not waiting for notification. Transitioning to Online.');
|
|
975
|
+
syncState = SyncState.Online;
|
|
976
|
+
setTimeout(() => ev.flush(), 0);
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
logger.info('History sync is enabled, awaiting notification with a 20s timeout.');
|
|
980
|
+
if (awaitingSyncTimeout) {
|
|
981
|
+
clearTimeout(awaitingSyncTimeout);
|
|
982
|
+
}
|
|
983
|
+
awaitingSyncTimeout = setTimeout(() => {
|
|
984
|
+
if (syncState === SyncState.AwaitingInitialSync) {
|
|
985
|
+
// TODO: investigate
|
|
986
|
+
logger.warn('Timeout in AwaitingInitialSync, forcing state to Online and flushing buffer');
|
|
987
|
+
syncState = SyncState.Online;
|
|
988
|
+
ev.flush();
|
|
973
989
|
}
|
|
990
|
+
}, 20000);
|
|
991
|
+
});
|
|
992
|
+
ev.on('lid-mapping.update', async ({ lid, pn }) => {
|
|
993
|
+
try {
|
|
994
|
+
await signalRepository.lidMapping.storeLIDPNMappings([{ lid, pn }]);
|
|
995
|
+
}
|
|
996
|
+
catch (error) {
|
|
997
|
+
logger.warn({ lid, pn, error }, 'Failed to store LID-PN mapping');
|
|
974
998
|
}
|
|
975
999
|
});
|
|
976
1000
|
return {
|
|
977
1001
|
...sock,
|
|
978
|
-
|
|
1002
|
+
createCallLink,
|
|
1003
|
+
getBotListV2,
|
|
1004
|
+
messageMutex,
|
|
1005
|
+
receiptMutex,
|
|
1006
|
+
appStatePatchMutex,
|
|
1007
|
+
notificationMutex,
|
|
979
1008
|
fetchPrivacySettings,
|
|
980
1009
|
upsertMessage,
|
|
981
1010
|
appPatch,
|
|
982
1011
|
sendPresenceUpdate,
|
|
983
1012
|
presenceSubscribe,
|
|
984
1013
|
profilePictureUrl,
|
|
985
|
-
onWhatsApp,
|
|
986
1014
|
fetchBlocklist,
|
|
987
1015
|
fetchStatus,
|
|
1016
|
+
fetchDisappearingDuration,
|
|
1017
|
+
findUserId,
|
|
988
1018
|
updateProfilePicture,
|
|
989
1019
|
removeProfilePicture,
|
|
990
1020
|
updateProfileStatus,
|
|
991
1021
|
updateProfileName,
|
|
992
1022
|
updateBlockStatus,
|
|
1023
|
+
updateDisableLinkPreviewsPrivacy,
|
|
1024
|
+
updateCallPrivacy,
|
|
1025
|
+
updateMessagesPrivacy,
|
|
993
1026
|
updateLastSeenPrivacy,
|
|
994
1027
|
updateOnlinePrivacy,
|
|
995
1028
|
updateProfilePicturePrivacy,
|
|
@@ -1001,13 +1034,15 @@ const makeChatsSocket = (config) => {
|
|
|
1001
1034
|
resyncAppState,
|
|
1002
1035
|
chatModify,
|
|
1003
1036
|
cleanDirtyBits,
|
|
1037
|
+
addOrEditContact,
|
|
1038
|
+
removeContact,
|
|
1039
|
+
addLabel,
|
|
1004
1040
|
addChatLabel,
|
|
1005
1041
|
removeChatLabel,
|
|
1006
1042
|
addMessageLabel,
|
|
1007
|
-
checkWhatsApp,
|
|
1008
|
-
reqPairing,
|
|
1009
1043
|
removeMessageLabel,
|
|
1010
|
-
star
|
|
1044
|
+
star,
|
|
1045
|
+
addOrEditQuickReply,
|
|
1046
|
+
removeQuickReply
|
|
1011
1047
|
};
|
|
1012
|
-
};
|
|
1013
|
-
exports.makeChatsSocket = makeChatsSocket;
|
|
1048
|
+
};
|