@heavstaltech/baileys 2.3.4 → 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +226 -53
- package/WAProto/index.js +14270 -302
- package/engine-requirements.js +10 -0
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/index.js +118 -79
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
- package/lib/Signal/Group/ciphertext-message.js +15 -0
- package/lib/Signal/Group/group-session-builder.d.ts +14 -0
- package/lib/Signal/Group/group-session-builder.js +64 -0
- package/lib/Signal/Group/group_cipher.d.ts +17 -0
- package/lib/Signal/Group/group_cipher.js +96 -0
- package/lib/Signal/Group/index.d.ts +11 -0
- package/lib/Signal/Group/index.js +57 -0
- package/lib/Signal/Group/keyhelper.d.ts +10 -0
- package/lib/Signal/Group/keyhelper.js +55 -0
- package/lib/Signal/Group/queue-job.d.ts +1 -0
- package/lib/Signal/Group/queue-job.js +57 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
- package/lib/Signal/Group/sender-chain-key.js +34 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
- package/lib/Signal/Group/sender-key-message.d.ts +18 -0
- package/lib/Signal/Group/sender-key-message.js +69 -0
- package/lib/Signal/Group/sender-key-name.d.ts +17 -0
- package/lib/Signal/Group/sender-key-name.js +51 -0
- package/lib/Signal/Group/sender-key-record.d.ts +30 -0
- package/lib/Signal/Group/sender-key-record.js +53 -0
- package/lib/Signal/Group/sender-key-state.d.ts +38 -0
- package/lib/Signal/Group/sender-key-state.js +99 -0
- package/lib/Signal/Group/sender-message-key.d.ts +11 -0
- package/{WASignalGroup/sender_message_key.js → lib/Signal/Group/sender-message-key.js} +6 -16
- package/lib/Signal/libsignal.js +51 -29
- package/lib/Socket/business.d.ts +43 -42
- package/lib/Socket/chats.d.ts +222 -36
- package/lib/Socket/chats.js +186 -153
- package/lib/Socket/dugong.d.ts +254 -0
- package/lib/Socket/dugong.js +484 -0
- package/lib/Socket/groups.d.ts +7 -7
- package/lib/Socket/groups.js +37 -35
- package/lib/Socket/index.d.ts +52 -51
- package/lib/Socket/index.js +1 -0
- package/lib/Socket/messages-recv.d.ts +37 -34
- package/lib/Socket/messages-recv.js +175 -37
- package/lib/Socket/messages-send.d.ts +12 -18
- package/lib/Socket/messages-send.js +396 -574
- package/lib/Socket/newsletter.d.ts +28 -26
- package/lib/Socket/newsletter.js +140 -25
- package/lib/Socket/registration.d.ts +52 -49
- package/lib/Socket/registration.js +7 -7
- package/lib/Socket/socket.d.ts +0 -1
- package/lib/Socket/socket.js +47 -198
- package/lib/Socket/usync.d.ts +10 -11
- package/lib/Store/make-cache-manager-store.d.ts +1 -2
- package/lib/Store/make-in-memory-store.d.ts +2 -2
- package/lib/Store/make-in-memory-store.js +1 -5
- package/lib/Store/make-ordered-dictionary.js +2 -2
- package/lib/Types/Auth.d.ts +1 -0
- package/lib/Types/Call.d.ts +1 -1
- package/lib/Types/Chat.d.ts +7 -12
- package/lib/Types/Events.d.ts +2 -17
- package/lib/Types/GroupMetadata.d.ts +2 -3
- package/lib/Types/Label.d.ts +0 -11
- package/lib/Types/Label.js +1 -1
- package/lib/Types/LabelAssociation.js +1 -1
- package/lib/Types/Message.d.ts +10 -170
- package/lib/Types/Newsletter.d.ts +97 -86
- package/lib/Types/Newsletter.js +38 -32
- package/lib/Types/Socket.d.ts +2 -7
- package/lib/Types/index.d.ts +0 -9
- package/lib/Types/index.js +1 -1
- package/lib/Utils/auth-utils.js +14 -35
- package/lib/Utils/business.d.ts +1 -1
- package/lib/Utils/business.js +2 -2
- package/lib/Utils/chat-utils.d.ts +12 -11
- package/lib/Utils/chat-utils.js +36 -52
- package/lib/Utils/crypto.d.ts +16 -15
- package/lib/Utils/crypto.js +26 -74
- package/lib/Utils/decode-wa-message.d.ts +0 -17
- package/lib/Utils/decode-wa-message.js +17 -53
- package/lib/Utils/event-buffer.js +7 -10
- package/lib/Utils/generics.d.ts +17 -13
- package/lib/Utils/generics.js +79 -58
- package/lib/Utils/history.d.ts +2 -6
- package/lib/Utils/history.js +6 -4
- package/lib/Utils/logger.d.ts +3 -1
- package/lib/Utils/lt-hash.js +12 -12
- package/lib/Utils/make-mutex.d.ts +2 -2
- package/lib/Utils/messages-media.d.ts +28 -25
- package/lib/Utils/messages-media.js +201 -103
- package/lib/Utils/messages.js +36 -473
- package/lib/Utils/noise-handler.d.ts +5 -4
- package/lib/Utils/noise-handler.js +14 -19
- package/lib/Utils/process-message.d.ts +5 -5
- package/lib/Utils/process-message.js +23 -75
- package/lib/Utils/signal.d.ts +1 -2
- package/lib/Utils/signal.js +26 -32
- package/lib/Utils/use-multi-file-auth-state.d.ts +1 -0
- package/lib/Utils/use-multi-file-auth-state.js +66 -242
- package/lib/Utils/validate-connection.d.ts +1 -1
- package/lib/Utils/validate-connection.js +88 -64
- package/lib/WABinary/constants.d.ts +27 -24
- package/lib/WABinary/decode.d.ts +2 -1
- package/lib/WABinary/decode.js +11 -23
- package/lib/WABinary/encode.d.ts +2 -1
- package/lib/WABinary/encode.js +147 -134
- package/lib/WABinary/generic-utils.d.ts +5 -2
- package/lib/WABinary/generic-utils.js +125 -37
- package/lib/WABinary/jid-utils.d.ts +1 -1
- package/lib/WAM/BinaryInfo.d.ts +11 -2
- package/lib/WAM/encode.d.ts +2 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +3 -3
- package/lib/WAUSync/USyncUser.d.ts +2 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +12 -0
- package/package.json +102 -98
- package/WAProto/index.d.ts +0 -50383
- package/WASignalGroup/GroupProtocol.js +0 -1697
- package/WASignalGroup/ciphertext_message.js +0 -16
- package/WASignalGroup/group_cipher.js +0 -120
- package/WASignalGroup/group_session_builder.js +0 -46
- package/WASignalGroup/index.js +0 -5
- package/WASignalGroup/keyhelper.js +0 -21
- package/WASignalGroup/protobufs.js +0 -3
- package/WASignalGroup/queue_job.js +0 -69
- package/WASignalGroup/sender_chain_key.js +0 -50
- package/WASignalGroup/sender_key_distribution_message.js +0 -78
- package/WASignalGroup/sender_key_message.js +0 -92
- package/WASignalGroup/sender_key_name.js +0 -70
- package/WASignalGroup/sender_key_record.js +0 -56
- package/WASignalGroup/sender_key_state.js +0 -129
- package/lib/Utils/use-single-file-auth-state.d.ts +0 -12
- package/lib/Utils/use-single-file-auth-state.js +0 -75
|
@@ -1,295 +1,119 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.useMultiFileAuthState = void 0;
|
|
7
|
-
const
|
|
4
|
+
const async_mutex_1 = require("async-mutex");
|
|
8
5
|
const promises_1 = require("fs/promises");
|
|
9
6
|
const path_1 = require("path");
|
|
10
7
|
const WAProto_1 = require("../../WAProto");
|
|
11
8
|
const auth_utils_1 = require("./auth-utils");
|
|
12
9
|
const generics_1 = require("./generics");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
timeout: 5000 // 5s timeout to prevent deadlocks
|
|
20
|
-
});
|
|
21
|
-
const globalAuthLock = new async_lock_1.default(); // Additional global lock
|
|
22
|
-
|
|
23
|
-
// Debugging utilities
|
|
24
|
-
let AUTH_DEBUG = false;
|
|
25
|
-
function authDebug(...args) {
|
|
26
|
-
if (AUTH_DEBUG) {
|
|
27
|
-
console.log('[AUTH DEBUG]', new Date().toISOString(), ...args);
|
|
10
|
+
const fileLocks = new Map();
|
|
11
|
+
const getFileLock = (path) => {
|
|
12
|
+
let mutex = fileLocks.get(path);
|
|
13
|
+
if (!mutex) {
|
|
14
|
+
mutex = new async_mutex_1.Mutex();
|
|
15
|
+
fileLocks.set(path, mutex);
|
|
28
16
|
}
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
return mutex;
|
|
18
|
+
};
|
|
31
19
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*/
|
|
38
|
-
const useMultiFileAuthState = async (folder
|
|
39
|
-
AUTH_DEBUG = options.authDebug ?? false;
|
|
40
|
-
const cache = options.syncCache ? new node_cache_1.default({
|
|
41
|
-
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.SIGNAL_STORE,
|
|
42
|
-
useClones: false,
|
|
43
|
-
deleteOnExpire: true,
|
|
44
|
-
checkperiod: 120
|
|
45
|
-
}) : null;
|
|
46
|
-
// Validate and prepare folder
|
|
47
|
-
const prepareFolder = async () => {
|
|
48
|
-
try {
|
|
49
|
-
const folderInfo = await (0, promises_1.stat)(folder).catch(() => null);
|
|
50
|
-
|
|
51
|
-
if (folderInfo) {
|
|
52
|
-
if (!folderInfo.isDirectory()) {
|
|
53
|
-
throw new Error(`Path exists but is not a directory: ${folder}`);
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
authDebug('Creating auth folder:', folder);
|
|
57
|
-
await (0, promises_1.mkdir)(folder, { recursive: true });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Verify folder is writable
|
|
61
|
-
await testFolderAccess();
|
|
62
|
-
} catch (error) {
|
|
63
|
-
authDebug('Folder preparation failed:', error);
|
|
64
|
-
throw new Error(`Auth folder initialization failed: ${error.message}`);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const testFolderAccess = async () => {
|
|
69
|
-
const testFile = (0, path_1.join)(folder, '.temp_test');
|
|
70
|
-
try {
|
|
71
|
-
await (0, promises_1.writeFile)(testFile, 'test');
|
|
72
|
-
await (0, promises_1.unlink)(testFile);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
throw new Error(`Folder not writable: ${error.message}`);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const fixFileName = (file) => {
|
|
79
|
-
if (!file) return file;
|
|
80
|
-
return file.replace(/\//g, '__').replace(/:/g, '-');
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
function getUniqueId(type, id) {
|
|
84
|
-
return `${type}.${id}`;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Enhanced write with retries
|
|
20
|
+
* stores the full authentication state in a single folder.
|
|
21
|
+
* Far more efficient than singlefileauthstate
|
|
22
|
+
*
|
|
23
|
+
* Again, I wouldn't endorse this for any production level use other than perhaps a bot.
|
|
24
|
+
* Would recommend writing an auth state for use with a proper SQL or No-SQL DB
|
|
25
|
+
* */
|
|
26
|
+
const useMultiFileAuthState = async (folder) => {
|
|
88
27
|
const writeData = async (data, file) => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
await fileLock.acquire(filePath, async () => {
|
|
98
|
-
const serialized = JSON.stringify(data, generics_1.BufferJSON.replacer);
|
|
99
|
-
await (0, promises_1.writeFile)(filePath, serialized);
|
|
100
|
-
authDebug('Write successful:', file);
|
|
101
|
-
});
|
|
102
|
-
return;
|
|
103
|
-
} catch (error) {
|
|
104
|
-
authDebug(`Write attempt ${attempts} failed for ${file}:`, error);
|
|
105
|
-
if (attempts >= maxAttempts) {
|
|
106
|
-
throw new Error(`Failed to write after ${maxAttempts} attempts: ${error.message}`);
|
|
107
|
-
}
|
|
108
|
-
await new Promise(resolve => setTimeout(resolve, 100 * attempts));
|
|
109
|
-
}
|
|
28
|
+
const filePath = (0, path_1.join)(folder, fixFileName(file));
|
|
29
|
+
const mutex = getFileLock(filePath);
|
|
30
|
+
return mutex.acquire().then(async (release) => {
|
|
31
|
+
try {
|
|
32
|
+
await (0, promises_1.writeFile)(filePath, JSON.stringify(data, generics_1.BufferJSON.replacer));
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
release();
|
|
110
36
|
}
|
|
111
37
|
});
|
|
112
38
|
};
|
|
113
|
-
|
|
114
|
-
// Enhanced read with validation
|
|
115
39
|
const readData = async (file) => {
|
|
116
|
-
|
|
40
|
+
try {
|
|
117
41
|
const filePath = (0, path_1.join)(folder, fixFileName(file));
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
return content;
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
const parsed = JSON.parse(data, generics_1.BufferJSON.reviver);
|
|
127
|
-
|
|
128
|
-
// Basic data validation
|
|
129
|
-
if (file === 'creds.json' && !parsed.me) {
|
|
130
|
-
authDebug('Invalid creds data detected');
|
|
131
|
-
return null;
|
|
42
|
+
const mutex = getFileLock(filePath);
|
|
43
|
+
return await mutex.acquire().then(async (release) => {
|
|
44
|
+
try {
|
|
45
|
+
const data = await (0, promises_1.readFile)(filePath, { encoding: 'utf-8' });
|
|
46
|
+
return JSON.parse(data, generics_1.BufferJSON.reviver);
|
|
132
47
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
} catch (error) {
|
|
136
|
-
if (error.code !== 'ENOENT') { // Ignore "file not found" errors
|
|
137
|
-
authDebug('Read error:', file, error);
|
|
48
|
+
finally {
|
|
49
|
+
release();
|
|
138
50
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
142
56
|
};
|
|
143
|
-
|
|
144
|
-
// Safe removal
|
|
145
57
|
const removeData = async (file) => {
|
|
146
|
-
|
|
58
|
+
try {
|
|
147
59
|
const filePath = (0, path_1.join)(folder, fixFileName(file));
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
60
|
+
const mutex = getFileLock(filePath);
|
|
61
|
+
return mutex.acquire().then(async (release) => {
|
|
62
|
+
try {
|
|
151
63
|
await (0, promises_1.unlink)(filePath);
|
|
152
|
-
authDebug('Removed:', file);
|
|
153
|
-
});
|
|
154
|
-
} catch (error) {
|
|
155
|
-
if (error.code !== 'ENOENT') { // Ignore "file not found" errors
|
|
156
|
-
authDebug('Remove error:', file, error);
|
|
157
64
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// Load or initialize credentials
|
|
166
|
-
let creds = await readData('creds.json');
|
|
167
|
-
if (!creds) {
|
|
168
|
-
authDebug('No existing creds found, initializing new ones');
|
|
169
|
-
creds = (0, auth_utils_1.initAuthCreds)();
|
|
170
|
-
await writeData(creds, 'creds.json');
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
async function warmUpCache() {
|
|
174
|
-
try {
|
|
175
|
-
const files = await promises_1.readdir(folder);
|
|
176
|
-
for (const file of files) {
|
|
177
|
-
if (file.endsWith('.json') && file !== 'creds.json') {
|
|
178
|
-
const parts = file.split('-');
|
|
179
|
-
if (parts.length === 2) {
|
|
180
|
-
const type = parts[0];
|
|
181
|
-
const id = parts[1].replace('.json', '');
|
|
182
|
-
const data = await readData(file);
|
|
183
|
-
if (data) {
|
|
184
|
-
cache.set(getUniqueId(type, id), data);
|
|
185
|
-
authDebug(`Cache warmed: ${type}-${id}`);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
65
|
+
catch (_a) {
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
release();
|
|
69
|
+
}
|
|
70
|
+
});
|
|
189
71
|
}
|
|
190
|
-
|
|
191
|
-
authDebug('Cache warm-up failed:', error);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (cache) warmUpCache();
|
|
196
|
-
|
|
197
|
-
// Auto-save mechanism
|
|
198
|
-
let saveTimeout;
|
|
199
|
-
const scheduleSave = () => {
|
|
200
|
-
if (saveTimeout) clearTimeout(saveTimeout);
|
|
201
|
-
saveTimeout = setTimeout(() => {
|
|
202
|
-
saveCreds().catch(error => {
|
|
203
|
-
authDebug('Auto-save failed, retrying sooner:', error);
|
|
204
|
-
setTimeout(scheduleSave, 60000);
|
|
205
|
-
});
|
|
206
|
-
}, 180000);
|
|
207
|
-
};
|
|
208
|
-
// Enhanced save function
|
|
209
|
-
const saveCreds = async () => {
|
|
210
|
-
try {
|
|
211
|
-
await writeData(creds, 'creds.json');
|
|
212
|
-
scheduleSave();
|
|
213
|
-
} catch (error) {
|
|
214
|
-
authDebug('Critical: Creds save failed:', error);
|
|
215
|
-
throw error;
|
|
72
|
+
catch (_a) {
|
|
216
73
|
}
|
|
217
74
|
};
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
await saveCreds().catch(e => {
|
|
230
|
-
authDebug('Emergency save failed:', e);
|
|
231
|
-
});
|
|
232
|
-
process.exit(1);
|
|
233
|
-
});
|
|
234
|
-
// Start auto-save loop
|
|
235
|
-
scheduleSave();
|
|
236
|
-
|
|
75
|
+
const folderInfo = await (0, promises_1.stat)(folder).catch(() => { });
|
|
76
|
+
if (folderInfo) {
|
|
77
|
+
if (!folderInfo.isDirectory()) {
|
|
78
|
+
throw new Error(`found something that is not a directory at ${folder}, either delete it or specify a different location`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
await (0, promises_1.mkdir)(folder, { recursive: true });
|
|
83
|
+
}
|
|
84
|
+
const fixFileName = (file) => { var _a; return (_a = file === null || file === void 0 ? void 0 : file.replace(/\//g, '__')) === null || _a === void 0 ? void 0 : _a.replace(/:/g, '-'); };
|
|
85
|
+
const creds = await readData('creds.json') || (0, auth_utils_1.initAuthCreds)();
|
|
237
86
|
return {
|
|
238
87
|
state: {
|
|
239
88
|
creds,
|
|
240
89
|
keys: {
|
|
241
90
|
get: async (type, ids) => {
|
|
242
91
|
const data = {};
|
|
243
|
-
|
|
244
92
|
await Promise.all(ids.map(async (id) => {
|
|
245
93
|
let value = await readData(`${type}-${id}.json`);
|
|
246
|
-
|
|
247
94
|
if (type === 'app-state-sync-key' && value) {
|
|
248
|
-
|
|
249
|
-
value = WAProto_1.proto.Message.AppStateSyncKeyData.fromObject(value);
|
|
250
|
-
} catch (error) {
|
|
251
|
-
authDebug('Key conversion failed:', type, id, error);
|
|
252
|
-
value = null;
|
|
253
|
-
}
|
|
95
|
+
value = WAProto_1.proto.Message.AppStateSyncKeyData.fromObject(value);
|
|
254
96
|
}
|
|
255
|
-
|
|
256
97
|
data[id] = value;
|
|
257
98
|
}));
|
|
258
|
-
|
|
259
99
|
return data;
|
|
260
100
|
},
|
|
261
101
|
set: async (data) => {
|
|
262
102
|
const tasks = [];
|
|
263
|
-
|
|
264
103
|
for (const category in data) {
|
|
265
104
|
for (const id in data[category]) {
|
|
266
105
|
const value = data[category][id];
|
|
267
106
|
const file = `${category}-${id}.json`;
|
|
268
|
-
|
|
269
|
-
if (value) {
|
|
270
|
-
tasks.push(writeData(value, file));
|
|
271
|
-
} else {
|
|
272
|
-
tasks.push(removeData(file));
|
|
273
|
-
}
|
|
107
|
+
tasks.push(value ? writeData(value, file) : removeData(file));
|
|
274
108
|
}
|
|
275
109
|
}
|
|
276
|
-
|
|
277
|
-
try {
|
|
278
|
-
await Promise.all(tasks);
|
|
279
|
-
} catch (error) {
|
|
280
|
-
authDebug('Bulk key update failed:', error);
|
|
281
|
-
throw error;
|
|
282
|
-
}
|
|
110
|
+
await Promise.all(tasks);
|
|
283
111
|
}
|
|
284
112
|
}
|
|
285
113
|
},
|
|
286
|
-
saveCreds
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if (saveTimeout) clearTimeout(saveTimeout);
|
|
290
|
-
await saveCreds();
|
|
291
|
-
},
|
|
292
|
-
cache
|
|
114
|
+
saveCreds: async () => {
|
|
115
|
+
return writeData(creds, 'creds.json');
|
|
116
|
+
}
|
|
293
117
|
};
|
|
294
118
|
};
|
|
295
|
-
exports.useMultiFileAuthState = useMultiFileAuthState;
|
|
119
|
+
exports.useMultiFileAuthState = useMultiFileAuthState;
|
|
@@ -7,5 +7,5 @@ export declare const generateRegistrationNode: ({ registrationId, signedPreKey,
|
|
|
7
7
|
export declare const configureSuccessfulPairing: (stanza: BinaryNode, { advSecretKey, signedIdentityKey, signalIdentities }: Pick<AuthenticationCreds, 'advSecretKey' | 'signedIdentityKey' | 'signalIdentities'>) => {
|
|
8
8
|
creds: Partial<AuthenticationCreds>;
|
|
9
9
|
reply: BinaryNode;
|
|
10
|
-
};
|
|
10
|
+
};
|
|
11
11
|
export declare const encodeSignedDeviceIdentity: (account: proto.IADVSignedDeviceIdentity, includeSignatureKey: boolean) => Uint8Array;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.encodeSignedDeviceIdentity = exports.configureSuccessfulPairing = exports.generateRegistrationNode = exports.generateLoginNode =
|
|
3
|
+
exports.encodeSignedDeviceIdentity = exports.configureSuccessfulPairing = exports.generateRegistrationNode = exports.generateLoginNode = void 0;
|
|
4
4
|
const boom_1 = require("@hapi/boom");
|
|
5
5
|
const crypto_1 = require("crypto");
|
|
6
6
|
const WAProto_1 = require("../../WAProto");
|
|
@@ -9,106 +9,107 @@ const WABinary_1 = require("../WABinary");
|
|
|
9
9
|
const crypto_2 = require("./crypto");
|
|
10
10
|
const generics_1 = require("./generics");
|
|
11
11
|
const signal_1 = require("./signal");
|
|
12
|
+
|
|
12
13
|
const getUserAgent = (config) => {
|
|
13
|
-
var _a, _b;
|
|
14
|
-
const osVersion = config.mobile ? '15.3.1' : '0.1';
|
|
15
|
-
const version = config.mobile ? [2, 24, 6] : config.version;
|
|
16
|
-
const device = config.mobile ? 'iPhone_7' : 'Desktop';
|
|
17
|
-
const manufacturer = config.mobile ? 'Apple' : '';
|
|
18
|
-
const platform = config.mobile ? WAProto_1.proto.ClientPayload.UserAgent.Platform.IOS : WAProto_1.proto.ClientPayload.UserAgent.Platform.WEB;
|
|
19
|
-
const phoneId = config.mobile ? { phoneId: config.auth.creds.phoneId } : {};
|
|
20
14
|
return {
|
|
21
15
|
appVersion: {
|
|
22
|
-
primary: version[0],
|
|
23
|
-
secondary: version[1],
|
|
24
|
-
tertiary: version[2],
|
|
16
|
+
primary: config.version[0],
|
|
17
|
+
secondary: config.version[1],
|
|
18
|
+
tertiary: config.version[2],
|
|
25
19
|
},
|
|
26
|
-
platform,
|
|
20
|
+
platform: WAProto_1.proto.ClientPayload.UserAgent.Platform.WEB,
|
|
27
21
|
releaseChannel: WAProto_1.proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
manufacturer,
|
|
32
|
-
device,
|
|
33
|
-
osBuildNumber: osVersion,
|
|
22
|
+
osVersion: '0.1',
|
|
23
|
+
device: 'Desktop',
|
|
24
|
+
osBuildNumber: '0.1',
|
|
34
25
|
localeLanguageIso6391: 'en',
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
mnc: '000',
|
|
27
|
+
mcc: '000',
|
|
28
|
+
localeCountryIso31661Alpha2: config.countryCode || 'US'
|
|
37
29
|
};
|
|
38
30
|
};
|
|
31
|
+
|
|
39
32
|
const PLATFORM_MAP = {
|
|
40
33
|
'Mac OS': WAProto_1.proto.ClientPayload.WebInfo.WebSubPlatform.DARWIN,
|
|
41
34
|
'Windows': WAProto_1.proto.ClientPayload.WebInfo.WebSubPlatform.WIN32
|
|
42
35
|
};
|
|
36
|
+
|
|
43
37
|
const getWebInfo = (config) => {
|
|
44
38
|
let webSubPlatform = WAProto_1.proto.ClientPayload.WebInfo.WebSubPlatform.WEB_BROWSER;
|
|
45
|
-
if (config.syncFullHistory && PLATFORM_MAP[config.browser[0]]) {
|
|
39
|
+
if (config.syncFullHistory && PLATFORM_MAP[config.browser[0]] && config.browser[1] === 'Desktop') {
|
|
46
40
|
webSubPlatform = PLATFORM_MAP[config.browser[0]];
|
|
47
41
|
}
|
|
48
42
|
return { webSubPlatform };
|
|
49
43
|
};
|
|
44
|
+
|
|
50
45
|
const getClientPayload = (config) => {
|
|
51
46
|
const payload = {
|
|
52
47
|
connectType: WAProto_1.proto.ClientPayload.ConnectType.WIFI_UNKNOWN,
|
|
53
48
|
connectReason: WAProto_1.proto.ClientPayload.ConnectReason.USER_ACTIVATED,
|
|
54
49
|
userAgent: getUserAgent(config),
|
|
55
50
|
};
|
|
56
|
-
|
|
57
|
-
payload.webInfo = getWebInfo(config);
|
|
58
|
-
}
|
|
51
|
+
payload.webInfo = getWebInfo(config);
|
|
59
52
|
return payload;
|
|
60
53
|
};
|
|
61
|
-
|
|
62
|
-
if (!config.auth.creds) {
|
|
63
|
-
throw new boom_1.Boom('No registration data found', { data: config });
|
|
64
|
-
}
|
|
65
|
-
const payload = {
|
|
66
|
-
...getClientPayload(config),
|
|
67
|
-
sessionId: Math.floor(Math.random() * 999999999 + 1),
|
|
68
|
-
shortConnect: true,
|
|
69
|
-
connectAttemptCount: 0,
|
|
70
|
-
device: 0,
|
|
71
|
-
dnsSource: {
|
|
72
|
-
appCached: false,
|
|
73
|
-
dnsMethod: WAProto_1.proto.ClientPayload.DNSSource.DNSResolutionMethod.SYSTEM,
|
|
74
|
-
},
|
|
75
|
-
passive: false,
|
|
76
|
-
pushName: 'test',
|
|
77
|
-
username: Number(`${config.auth.creds.registration.phoneNumberCountryCode}${config.auth.creds.registration.phoneNumberNationalNumber}`),
|
|
78
|
-
};
|
|
79
|
-
return WAProto_1.proto.ClientPayload.fromObject(payload);
|
|
80
|
-
};
|
|
81
|
-
exports.generateMobileNode = generateMobileNode;
|
|
54
|
+
|
|
82
55
|
const generateLoginNode = (userJid, config) => {
|
|
83
56
|
const { user, device } = (0, WABinary_1.jidDecode)(userJid);
|
|
84
57
|
const payload = {
|
|
85
58
|
...getClientPayload(config),
|
|
86
59
|
passive: true,
|
|
60
|
+
pull: true,
|
|
87
61
|
username: +user,
|
|
88
62
|
device: device,
|
|
63
|
+
lidDbMigrated: false
|
|
89
64
|
};
|
|
90
65
|
return WAProto_1.proto.ClientPayload.fromObject(payload);
|
|
91
66
|
};
|
|
92
67
|
exports.generateLoginNode = generateLoginNode;
|
|
68
|
+
|
|
93
69
|
const getPlatformType = (platform) => {
|
|
94
70
|
const platformType = platform.toUpperCase();
|
|
95
|
-
return WAProto_1.proto.DeviceProps.PlatformType[platformType] || WAProto_1.proto.DeviceProps.PlatformType.
|
|
71
|
+
return WAProto_1.proto.DeviceProps.PlatformType[platformType] || WAProto_1.proto.DeviceProps.PlatformType.CHROME;
|
|
96
72
|
};
|
|
73
|
+
|
|
97
74
|
const generateRegistrationNode = ({ registrationId, signedPreKey, signedIdentityKey }, config) => {
|
|
98
|
-
// the app version needs to be md5 hashed
|
|
99
|
-
// and passed in
|
|
100
75
|
const appVersionBuf = (0, crypto_1.createHash)('md5')
|
|
101
|
-
.update(config.version.join('.'))
|
|
76
|
+
.update(config.version.join('.'))
|
|
102
77
|
.digest();
|
|
78
|
+
|
|
103
79
|
const companion = {
|
|
104
80
|
os: config.browser[0],
|
|
105
81
|
platformType: getPlatformType(config.browser[1]),
|
|
106
82
|
requireFullSync: config.syncFullHistory,
|
|
83
|
+
historySyncConfig: {
|
|
84
|
+
storageQuotaMb: 10240,
|
|
85
|
+
inlineInitialPayloadInE2EeMsg: true,
|
|
86
|
+
recentSyncDaysLimit: undefined,
|
|
87
|
+
supportCallLogHistory: false,
|
|
88
|
+
supportBotUserAgentChatHistory: true,
|
|
89
|
+
supportCagReactionsAndPolls: true,
|
|
90
|
+
supportBizHostedMsg: true,
|
|
91
|
+
supportRecentSyncChunkMessageCountTuning: true,
|
|
92
|
+
supportHostedGroupMsg: true,
|
|
93
|
+
supportFbidBotChatHistory: true,
|
|
94
|
+
supportAddOnHistorySyncMigration: undefined,
|
|
95
|
+
supportMessageAssociation: true,
|
|
96
|
+
supportGroupHistory: false,
|
|
97
|
+
onDemandReady: undefined,
|
|
98
|
+
supportGuestChat: undefined
|
|
99
|
+
},
|
|
100
|
+
version: {
|
|
101
|
+
primary: 10,
|
|
102
|
+
secondary: 15,
|
|
103
|
+
tertiary: 7
|
|
104
|
+
}
|
|
107
105
|
};
|
|
106
|
+
|
|
108
107
|
const companionProto = WAProto_1.proto.DeviceProps.encode(companion).finish();
|
|
108
|
+
|
|
109
109
|
const registerPayload = {
|
|
110
110
|
...getClientPayload(config),
|
|
111
111
|
passive: false,
|
|
112
|
+
pull: false,
|
|
112
113
|
devicePairingData: {
|
|
113
114
|
buildHash: appVersionBuf,
|
|
114
115
|
deviceProps: companionProto,
|
|
@@ -123,6 +124,7 @@ const generateRegistrationNode = ({ registrationId, signedPreKey, signedIdentity
|
|
|
123
124
|
return WAProto_1.proto.ClientPayload.fromObject(registerPayload);
|
|
124
125
|
};
|
|
125
126
|
exports.generateRegistrationNode = generateRegistrationNode;
|
|
127
|
+
|
|
126
128
|
const configureSuccessfulPairing = (stanza, { advSecretKey, signedIdentityKey, signalIdentities }) => {
|
|
127
129
|
const msgId = stanza.attrs.id;
|
|
128
130
|
const pairSuccessNode = (0, WABinary_1.getBinaryNodeChild)(stanza, 'pair-success');
|
|
@@ -130,30 +132,52 @@ const configureSuccessfulPairing = (stanza, { advSecretKey, signedIdentityKey, s
|
|
|
130
132
|
const platformNode = (0, WABinary_1.getBinaryNodeChild)(pairSuccessNode, 'platform');
|
|
131
133
|
const deviceNode = (0, WABinary_1.getBinaryNodeChild)(pairSuccessNode, 'device');
|
|
132
134
|
const businessNode = (0, WABinary_1.getBinaryNodeChild)(pairSuccessNode, 'biz');
|
|
135
|
+
|
|
133
136
|
if (!deviceIdentityNode || !deviceNode) {
|
|
134
137
|
throw new boom_1.Boom('Missing device-identity or device in pair success node', { data: stanza });
|
|
135
138
|
}
|
|
136
|
-
|
|
139
|
+
|
|
140
|
+
const bizName = businessNode?.attrs.name;
|
|
137
141
|
const jid = deviceNode.attrs.jid;
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
const
|
|
142
|
+
const lid = deviceNode.attrs.lid;
|
|
143
|
+
|
|
144
|
+
const { details, hmac, accountType } = WAProto_1.proto.ADVSignedDeviceIdentityHMAC.decode(deviceIdentityNode.content);
|
|
145
|
+
|
|
146
|
+
let hmacPrefix = Buffer.from([]);
|
|
147
|
+
if (accountType !== undefined && accountType === WAProto_1.proto.ADVEncryptionType.HOSTED) {
|
|
148
|
+
hmacPrefix = Buffer.from([0x06, 0x05]);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const advSign = (0, crypto_2.hmacSign)(Buffer.concat([hmacPrefix, details]), Buffer.from(advSecretKey, 'base64'));
|
|
141
152
|
if (Buffer.compare(hmac, advSign) !== 0) {
|
|
142
153
|
throw new boom_1.Boom('Invalid account signature');
|
|
143
154
|
}
|
|
155
|
+
|
|
144
156
|
const account = WAProto_1.proto.ADVSignedDeviceIdentity.decode(details);
|
|
145
157
|
const { accountSignatureKey, accountSignature, details: deviceDetails } = account;
|
|
146
|
-
|
|
147
|
-
const
|
|
158
|
+
|
|
159
|
+
const deviceIdentity = WAProto_1.proto.ADVDeviceIdentity.decode(deviceDetails);
|
|
160
|
+
|
|
161
|
+
const accountSignaturePrefix = deviceIdentity.deviceType === WAProto_1.proto.ADVEncryptionType.HOSTED
|
|
162
|
+
? Buffer.from([0x06, 0x05])
|
|
163
|
+
: Buffer.from([0x06, 0x00]);
|
|
164
|
+
const accountMsg = Buffer.concat([accountSignaturePrefix, deviceDetails, signedIdentityKey.public]);
|
|
165
|
+
|
|
148
166
|
if (!crypto_2.Curve.verify(accountSignatureKey, accountMsg, accountSignature)) {
|
|
149
167
|
throw new boom_1.Boom('Failed to verify account signature');
|
|
150
168
|
}
|
|
151
|
-
|
|
152
|
-
const deviceMsg = Buffer.concat([
|
|
169
|
+
|
|
170
|
+
const deviceMsg = Buffer.concat([
|
|
171
|
+
Buffer.from([0x06, 0x01]),
|
|
172
|
+
deviceDetails,
|
|
173
|
+
signedIdentityKey.public,
|
|
174
|
+
accountSignatureKey
|
|
175
|
+
]);
|
|
153
176
|
account.deviceSignature = crypto_2.Curve.sign(signedIdentityKey.private, deviceMsg);
|
|
177
|
+
|
|
154
178
|
const identity = (0, signal_1.createSignalIdentity)(jid, accountSignatureKey);
|
|
155
179
|
const accountEnc = (0, exports.encodeSignedDeviceIdentity)(account, false);
|
|
156
|
-
|
|
180
|
+
|
|
157
181
|
const reply = {
|
|
158
182
|
tag: 'iq',
|
|
159
183
|
attrs: {
|
|
@@ -175,27 +199,27 @@ const configureSuccessfulPairing = (stanza, { advSecretKey, signedIdentityKey, s
|
|
|
175
199
|
}
|
|
176
200
|
]
|
|
177
201
|
};
|
|
202
|
+
|
|
178
203
|
const authUpdate = {
|
|
179
204
|
account,
|
|
180
|
-
me: { id: jid, name: bizName },
|
|
205
|
+
me: { id: jid, name: bizName, lid },
|
|
181
206
|
signalIdentities: [
|
|
182
207
|
...(signalIdentities || []),
|
|
183
208
|
identity
|
|
184
209
|
],
|
|
185
|
-
platform: platformNode
|
|
210
|
+
platform: platformNode?.attrs.name
|
|
186
211
|
};
|
|
212
|
+
|
|
187
213
|
return {
|
|
188
214
|
creds: authUpdate,
|
|
189
215
|
reply
|
|
190
216
|
};
|
|
191
217
|
};
|
|
192
218
|
exports.configureSuccessfulPairing = configureSuccessfulPairing;
|
|
219
|
+
|
|
193
220
|
const encodeSignedDeviceIdentity = (account, includeSignatureKey) => {
|
|
194
|
-
var _a;
|
|
195
221
|
account = { ...account };
|
|
196
|
-
|
|
197
|
-
// or if we are including the signature key but it is empty
|
|
198
|
-
if (!includeSignatureKey || !((_a = account.accountSignatureKey) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
222
|
+
if (!includeSignatureKey || !account.accountSignatureKey?.length) {
|
|
199
223
|
account.accountSignatureKey = null;
|
|
200
224
|
}
|
|
201
225
|
return WAProto_1.proto.ADVSignedDeviceIdentity
|