@hbmodsofc/baileys 1.5.0 → 1.7.6

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.
Files changed (156) hide show
  1. package/LICENSE +1 -1
  2. package/WAProto/index.js +19671 -152026
  3. package/engine-requirements.js +4 -4
  4. package/lib/Defaults/index.d.ts +12 -8
  5. package/lib/Defaults/index.js +90 -124
  6. package/lib/Signal/Group/group_cipher.d.ts +0 -1
  7. package/lib/Signal/Group/group_cipher.js +28 -39
  8. package/lib/Signal/Group/sender-chain-key.d.ts +1 -1
  9. package/lib/Signal/Group/sender-chain-key.js +9 -2
  10. package/lib/Signal/Group/sender-key-distribution-message.js +3 -3
  11. package/lib/Signal/Group/sender-key-message.js +3 -3
  12. package/lib/Signal/Group/sender-key-state.d.ts +4 -4
  13. package/lib/Signal/Group/sender-key-state.js +47 -16
  14. package/lib/Signal/libsignal.d.ts +7 -3
  15. package/lib/Signal/libsignal.js +224 -39
  16. package/lib/Signal/lid-mapping.d.ts +26 -0
  17. package/lib/Signal/lid-mapping.js +146 -0
  18. package/lib/Socket/Client/index.d.ts +2 -3
  19. package/lib/Socket/Client/index.js +2 -3
  20. package/lib/Socket/Client/{abstract-socket-client.d.ts → types.d.ts} +1 -3
  21. package/lib/Socket/Client/{web-socket-client.d.ts → websocket.d.ts} +1 -1
  22. package/lib/Socket/Client/{web-socket-client.js → websocket.js} +10 -16
  23. package/lib/Socket/business.d.ts +94 -78
  24. package/lib/Socket/business.js +130 -11
  25. package/lib/Socket/chats.d.ts +63 -233
  26. package/lib/Socket/chats.js +234 -184
  27. package/lib/Socket/communities.d.ts +232 -0
  28. package/lib/Socket/communities.js +402 -0
  29. package/lib/Socket/groups.d.ts +62 -41
  30. package/lib/Socket/groups.js +76 -64
  31. package/lib/Socket/index.d.ts +129 -83
  32. package/lib/Socket/index.js +13 -6
  33. package/lib/Socket/messages-recv.d.ts +59 -48
  34. package/lib/Socket/messages-recv.js +516 -371
  35. package/lib/Socket/messages-send.d.ts +86 -67
  36. package/lib/Socket/messages-send.js +1091 -1
  37. package/lib/Socket/mex.d.ts +2 -0
  38. package/lib/Socket/mex.js +45 -0
  39. package/lib/Socket/newsletter.d.ts +76 -64
  40. package/lib/Socket/newsletter.js +184 -1
  41. package/lib/Socket/socket.d.ts +19 -13
  42. package/lib/Socket/socket.js +805 -1
  43. package/lib/Types/Auth.d.ts +4 -10
  44. package/lib/Types/Bussines.d.ts +24 -0
  45. package/lib/Types/Bussines.js +2 -0
  46. package/lib/Types/Call.d.ts +1 -1
  47. package/lib/Types/Chat.d.ts +29 -9
  48. package/lib/Types/Chat.js +7 -1
  49. package/lib/Types/Contact.d.ts +5 -1
  50. package/lib/Types/Events.d.ts +55 -14
  51. package/lib/Types/GroupMetadata.d.ts +15 -5
  52. package/lib/Types/Label.d.ts +11 -0
  53. package/lib/Types/Label.js +1 -1
  54. package/lib/Types/LabelAssociation.js +1 -1
  55. package/lib/Types/Message.d.ts +75 -49
  56. package/lib/Types/Message.js +10 -7
  57. package/lib/Types/Newsletter.d.ts +129 -98
  58. package/lib/Types/Newsletter.js +33 -38
  59. package/lib/Types/Product.d.ts +1 -1
  60. package/lib/Types/Signal.d.ts +29 -1
  61. package/lib/Types/Socket.d.ts +48 -22
  62. package/lib/Types/State.d.ts +13 -2
  63. package/lib/Types/State.js +12 -0
  64. package/lib/Types/USync.d.ts +1 -1
  65. package/lib/Types/index.d.ts +10 -3
  66. package/lib/Types/index.js +2 -2
  67. package/lib/Utils/auth-utils.d.ts +3 -3
  68. package/lib/Utils/auth-utils.js +378 -102
  69. package/lib/Utils/baileys-event-stream.js +1 -1
  70. package/lib/Utils/business.d.ts +2 -2
  71. package/lib/Utils/business.js +19 -13
  72. package/lib/Utils/chat-utils.d.ts +21 -22
  73. package/lib/Utils/chat-utils.js +201 -154
  74. package/lib/Utils/crypto.d.ts +18 -19
  75. package/lib/Utils/crypto.js +78 -37
  76. package/lib/Utils/decode-wa-message.d.ts +34 -7
  77. package/lib/Utils/decode-wa-message.js +138 -66
  78. package/lib/Utils/event-buffer.d.ts +6 -8
  79. package/lib/Utils/event-buffer.js +81 -43
  80. package/lib/Utils/generics.d.ts +27 -27
  81. package/lib/Utils/generics.js +128 -133
  82. package/lib/Utils/history.d.ts +9 -5
  83. package/lib/Utils/history.js +17 -23
  84. package/lib/Utils/index.d.ts +2 -0
  85. package/lib/Utils/index.js +2 -0
  86. package/lib/Utils/lidToJid-test.d.ts +11 -0
  87. package/lib/Utils/lidToJid-test.js +27 -0
  88. package/lib/Utils/link-preview.d.ts +4 -4
  89. package/lib/Utils/link-preview.js +40 -12
  90. package/lib/Utils/logger.d.ts +11 -3
  91. package/lib/Utils/lt-hash.d.ts +8 -8
  92. package/lib/Utils/lt-hash.js +23 -24
  93. package/lib/Utils/make-mutex.d.ts +2 -2
  94. package/lib/Utils/make-mutex.js +3 -2
  95. package/lib/Utils/message-retry-manager.d.ts +81 -0
  96. package/lib/Utils/message-retry-manager.js +152 -0
  97. package/lib/Utils/messages-media.d.ts +37 -41
  98. package/lib/Utils/messages-media.js +252 -368
  99. package/lib/Utils/messages.d.ts +13 -15
  100. package/lib/Utils/messages.js +274 -261
  101. package/lib/Utils/noise-handler.d.ts +13 -15
  102. package/lib/Utils/noise-handler.js +20 -26
  103. package/lib/Utils/process-message.d.ts +9 -8
  104. package/lib/Utils/process-message.js +157 -93
  105. package/lib/Utils/signal.d.ts +6 -5
  106. package/lib/Utils/signal.js +37 -29
  107. package/lib/Utils/use-multi-file-auth-state.d.ts +1 -2
  108. package/lib/Utils/use-multi-file-auth-state.js +12 -7
  109. package/lib/Utils/validate-connection.d.ts +5 -6
  110. package/lib/Utils/validate-connection.js +39 -97
  111. package/lib/WABinary/constants.d.ts +24 -27
  112. package/lib/WABinary/constants.js +1276 -13
  113. package/lib/WABinary/decode.d.ts +3 -4
  114. package/lib/WABinary/decode.js +28 -14
  115. package/lib/WABinary/encode.d.ts +1 -2
  116. package/lib/WABinary/encode.js +134 -147
  117. package/lib/WABinary/generic-utils.d.ts +4 -7
  118. package/lib/WABinary/generic-utils.js +40 -125
  119. package/lib/WABinary/jid-utils.d.ts +13 -8
  120. package/lib/WABinary/jid-utils.js +27 -16
  121. package/lib/WAM/BinaryInfo.d.ts +2 -11
  122. package/lib/WAM/constants.d.ts +3 -2
  123. package/lib/WAM/constants.js +2252 -2359
  124. package/lib/WAM/encode.d.ts +1 -2
  125. package/lib/WAM/encode.js +8 -11
  126. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +2 -2
  127. package/lib/WAUSync/Protocols/USyncContactProtocol.js +3 -4
  128. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +2 -2
  129. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +5 -5
  130. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +2 -2
  131. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +5 -5
  132. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +2 -2
  133. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +5 -6
  134. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +2 -2
  135. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +1 -1
  136. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +4 -3
  137. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +11 -3
  138. package/lib/WAUSync/USyncQuery.d.ts +2 -2
  139. package/lib/WAUSync/USyncQuery.js +19 -15
  140. package/lib/WAUSync/USyncUser.d.ts +5 -5
  141. package/lib/WAUSync/index.d.ts +1 -1
  142. package/lib/WAUSync/index.js +1 -1
  143. package/package.json +102 -102
  144. package/lib/Defaults/baileys-version.json +0 -3
  145. package/lib/Defaults/phonenumber-mcc.json +0 -223
  146. package/lib/Signal/Group/queue-job.d.ts +0 -1
  147. package/lib/Signal/Group/queue-job.js +0 -57
  148. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  149. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  150. package/lib/Socket/hbmods.d.ts +0 -253
  151. package/lib/Socket/hbmods.js +0 -1
  152. package/lib/Socket/registration.d.ts +0 -267
  153. package/lib/Socket/registration.js +0 -166
  154. package/lib/Socket/usync.d.ts +0 -36
  155. package/lib/Socket/usync.js +0 -70
  156. /package/lib/Socket/Client/{abstract-socket-client.js → types.js} +0 -0
@@ -34,19 +34,34 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.makeLibSignalRepository = makeLibSignalRepository;
37
+ /* @ts-ignore */
37
38
  const libsignal = __importStar(require("libsignal"));
38
39
  const Utils_1 = require("../Utils");
39
40
  const WABinary_1 = require("../WABinary");
40
41
  const sender_key_name_1 = require("./Group/sender-key-name");
41
42
  const sender_key_record_1 = require("./Group/sender-key-record");
42
43
  const Group_1 = require("./Group");
43
- function makeLibSignalRepository(auth) {
44
- const storage = signalStorage(auth);
45
- return {
44
+ const lid_mapping_1 = require("./lid-mapping");
45
+ function makeLibSignalRepository(auth, onWhatsAppFunc) {
46
+ const lidMapping = new lid_mapping_1.LIDMappingStore(auth.keys, onWhatsAppFunc);
47
+ const storage = signalStorage(auth, lidMapping);
48
+ const parsedKeys = auth.keys;
49
+ function isLikelySyncMessage(addr) {
50
+ const key = addr.toString();
51
+ // Only bypass for WhatsApp system addresses, not regular user contacts
52
+ // Be very specific about sync service patterns
53
+ return (key.includes('@lid.whatsapp.net') || // WhatsApp system messages
54
+ key.includes('@broadcast') || // Broadcast messages
55
+ key.includes('@newsletter'));
56
+ }
57
+ const repository = {
46
58
  decryptGroupMessage({ group, authorJid, msg }) {
47
59
  const senderName = jidToSignalSenderKeyName(group, authorJid);
48
60
  const cipher = new Group_1.GroupCipher(storage, senderName);
49
- return cipher.decrypt(msg);
61
+ // Use transaction to ensure atomicity
62
+ return parsedKeys.transaction(async () => {
63
+ return cipher.decrypt(msg);
64
+ }, group);
50
65
  },
51
66
  async processSenderKeyDistributionMessage({ item, authorJid }) {
52
67
  const builder = new Group_1.GroupSessionBuilder(storage);
@@ -60,70 +75,240 @@ function makeLibSignalRepository(auth) {
60
75
  if (!senderKey) {
61
76
  await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord());
62
77
  }
63
- await builder.process(senderName, senderMsg);
78
+ return parsedKeys.transaction(async () => {
79
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
80
+ if (!senderKey) {
81
+ await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord());
82
+ }
83
+ await builder.process(senderName, senderMsg);
84
+ }, item.groupId);
64
85
  },
65
86
  async decryptMessage({ jid, type, ciphertext }) {
66
87
  const addr = jidToSignalProtocolAddress(jid);
67
88
  const session = new libsignal.SessionCipher(storage, addr);
68
- let result;
69
- switch (type) {
70
- case 'pkmsg':
71
- result = await session.decryptPreKeyWhisperMessage(ciphertext);
72
- break;
73
- case 'msg':
74
- result = await session.decryptWhisperMessage(ciphertext);
75
- break;
76
- default:
77
- throw new Error(`Unknown message type: ${type}`);
89
+ async function doDecrypt() {
90
+ let result;
91
+ switch (type) {
92
+ case 'pkmsg':
93
+ result = await session.decryptPreKeyWhisperMessage(ciphertext);
94
+ break;
95
+ case 'msg':
96
+ result = await session.decryptWhisperMessage(ciphertext);
97
+ break;
98
+ }
99
+ return result;
100
+ }
101
+ if (isLikelySyncMessage(addr)) {
102
+ // If it's a sync message, we can skip the transaction
103
+ // as it is likely to be a system message that doesn't require strict atomicity
104
+ return await doDecrypt();
78
105
  }
79
- return result;
106
+ // If it's not a sync message, we need to ensure atomicity
107
+ // For regular messages, we use a transaction to ensure atomicity
108
+ return parsedKeys.transaction(async () => {
109
+ return await doDecrypt();
110
+ }, jid);
80
111
  },
81
112
  async encryptMessage({ jid, data }) {
82
- const addr = jidToSignalProtocolAddress(jid);
113
+ // LID SINGLE SOURCE OF TRUTH: Always prefer LID when available
114
+ let encryptionJid = jid;
115
+ // Check for LID mapping and use it if session exists
116
+ if (jid.includes('@s.whatsapp.net')) {
117
+ const lidForPN = await lidMapping.getLIDForPN(jid);
118
+ if (lidForPN?.includes('@lid')) {
119
+ const lidAddr = jidToSignalProtocolAddress(lidForPN);
120
+ const { [lidAddr.toString()]: lidSession } = await auth.keys.get('session', [lidAddr.toString()]);
121
+ if (lidSession) {
122
+ // LID session exists, use it
123
+ encryptionJid = lidForPN;
124
+ }
125
+ else {
126
+ // Try to migrate if PN session exists
127
+ const pnAddr = jidToSignalProtocolAddress(jid);
128
+ const { [pnAddr.toString()]: pnSession } = await auth.keys.get('session', [pnAddr.toString()]);
129
+ if (pnSession) {
130
+ // Migrate PN to LID
131
+ await repository.migrateSession([jid], lidForPN);
132
+ encryptionJid = lidForPN;
133
+ }
134
+ }
135
+ }
136
+ }
137
+ const addr = jidToSignalProtocolAddress(encryptionJid);
83
138
  const cipher = new libsignal.SessionCipher(storage, addr);
84
- const { type: sigType, body } = await cipher.encrypt(data);
85
- const type = sigType === 3 ? 'pkmsg' : 'msg';
86
- return { type, ciphertext: Buffer.from(body, 'binary') };
139
+ // Use transaction to ensure atomicity
140
+ return parsedKeys.transaction(async () => {
141
+ const { type: sigType, body } = await cipher.encrypt(data);
142
+ const type = sigType === 3 ? 'pkmsg' : 'msg';
143
+ return { type, ciphertext: Buffer.from(body, 'binary') };
144
+ }, jid);
87
145
  },
88
146
  async encryptGroupMessage({ group, meId, data }) {
89
147
  const senderName = jidToSignalSenderKeyName(group, meId);
90
148
  const builder = new Group_1.GroupSessionBuilder(storage);
91
149
  const senderNameStr = senderName.toString();
92
- const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
93
- if (!senderKey) {
94
- await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord());
95
- }
96
- const senderKeyDistributionMessage = await builder.create(senderName);
97
- const session = new Group_1.GroupCipher(storage, senderName);
98
- const ciphertext = await session.encrypt(data);
99
- return {
100
- ciphertext,
101
- senderKeyDistributionMessage: senderKeyDistributionMessage.serialize()
102
- };
150
+ return parsedKeys.transaction(async () => {
151
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
152
+ if (!senderKey) {
153
+ await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord());
154
+ }
155
+ const senderKeyDistributionMessage = await builder.create(senderName);
156
+ const session = new Group_1.GroupCipher(storage, senderName);
157
+ const ciphertext = await session.encrypt(data);
158
+ return {
159
+ ciphertext,
160
+ senderKeyDistributionMessage: senderKeyDistributionMessage.serialize()
161
+ };
162
+ }, group);
103
163
  },
104
164
  async injectE2ESession({ jid, session }) {
105
165
  const cipher = new libsignal.SessionBuilder(storage, jidToSignalProtocolAddress(jid));
106
- await cipher.initOutgoing(session);
166
+ return parsedKeys.transaction(async () => {
167
+ await cipher.initOutgoing(session);
168
+ }, jid);
107
169
  },
108
170
  jidToSignalProtocolAddress(jid) {
109
171
  return jidToSignalProtocolAddress(jid).toString();
172
+ },
173
+ // Optimized direct access to LID mapping store
174
+ lidMapping,
175
+ async validateSession(jid) {
176
+ try {
177
+ const addr = jidToSignalProtocolAddress(jid);
178
+ const session = await storage.loadSession(addr.toString());
179
+ if (!session) {
180
+ return { exists: false, reason: 'no session' };
181
+ }
182
+ if (!session.haveOpenSession()) {
183
+ return { exists: false, reason: 'no open session' };
184
+ }
185
+ return { exists: true };
186
+ }
187
+ catch (error) {
188
+ return { exists: false, reason: 'validation error' };
189
+ }
190
+ },
191
+ async deleteSession(jids) {
192
+ if (!jids.length)
193
+ return;
194
+ // Convert JIDs to signal addresses and prepare for bulk deletion
195
+ const sessionUpdates = {};
196
+ jids.forEach(jid => {
197
+ const addr = jidToSignalProtocolAddress(jid);
198
+ sessionUpdates[addr.toString()] = null;
199
+ });
200
+ // Single transaction for all deletions
201
+ return parsedKeys.transaction(async () => {
202
+ await auth.keys.set({ session: sessionUpdates });
203
+ }, `delete-${jids.length}-sessions`);
204
+ },
205
+ async migrateSession(fromJids, toJid) {
206
+ if (!fromJids.length || !toJid.includes('@lid'))
207
+ return { migrated: 0, skipped: 0, total: 0 };
208
+ // Filter valid PN JIDs
209
+ const validJids = fromJids.filter(jid => jid.includes('@s.whatsapp.net'));
210
+ if (!validJids.length)
211
+ return { migrated: 0, skipped: 0, total: fromJids.length };
212
+ // Single optimized transaction for all migrations
213
+ return parsedKeys.transaction(async () => {
214
+ // 1. Batch store all LID mappings
215
+ const mappings = validJids.map(jid => ({
216
+ lid: (0, WABinary_1.transferDevice)(jid, toJid),
217
+ pn: jid
218
+ }));
219
+ await lidMapping.storeLIDPNMappings(mappings);
220
+ // 2. Prepare migration operations
221
+ const migrationOps = validJids.map(jid => {
222
+ const lidWithDevice = (0, WABinary_1.transferDevice)(jid, toJid);
223
+ const fromDecoded = (0, WABinary_1.jidDecode)(jid);
224
+ const toDecoded = (0, WABinary_1.jidDecode)(lidWithDevice);
225
+ return {
226
+ fromJid: jid,
227
+ toJid: lidWithDevice,
228
+ pnUser: fromDecoded.user,
229
+ lidUser: toDecoded.user,
230
+ deviceId: fromDecoded.device || 0,
231
+ fromAddr: jidToSignalProtocolAddress(jid),
232
+ toAddr: jidToSignalProtocolAddress(lidWithDevice)
233
+ };
234
+ });
235
+ // 3. Batch check which LID sessions already exist
236
+ const lidAddrs = migrationOps.map(op => op.toAddr.toString());
237
+ const existingSessions = await auth.keys.get('session', lidAddrs);
238
+ // 4. Filter out sessions that already have LID sessions
239
+ const opsToMigrate = migrationOps.filter(op => !existingSessions[op.toAddr.toString()]);
240
+ const skippedCount = migrationOps.length - opsToMigrate.length;
241
+ if (!opsToMigrate.length) {
242
+ return { migrated: 0, skipped: skippedCount, total: validJids.length };
243
+ }
244
+ // 5. Execute all migrations in parallel
245
+ await Promise.all(opsToMigrate.map(async (op) => {
246
+ const fromSession = await storage.loadSession(op.fromAddr.toString());
247
+ if (fromSession?.haveOpenSession()) {
248
+ // Copy session to LID address
249
+ const sessionBytes = fromSession.serialize();
250
+ const copiedSession = libsignal.SessionRecord.deserialize(sessionBytes);
251
+ await storage.storeSession(op.toAddr.toString(), copiedSession);
252
+ // Delete PN session
253
+ await auth.keys.set({ session: { [op.fromAddr.toString()]: null } });
254
+ }
255
+ }));
256
+ return { migrated: opsToMigrate.length, skipped: skippedCount, total: validJids.length };
257
+ }, `migrate-${validJids.length}-sessions-${(0, WABinary_1.jidDecode)(toJid)?.user}`);
258
+ },
259
+ async encryptMessageWithWire({ encryptionJid, wireJid, data }) {
260
+ const result = await repository.encryptMessage({ jid: encryptionJid, data });
261
+ return { ...result, wireJid };
110
262
  }
111
263
  };
264
+ return repository;
112
265
  }
113
266
  const jidToSignalProtocolAddress = (jid) => {
114
- const { user, device } = (0, WABinary_1.jidDecode)(jid);
115
- return new libsignal.ProtocolAddress(user, device || 0);
267
+ const decoded = (0, WABinary_1.jidDecode)(jid);
268
+ const { user, device, server } = decoded;
269
+ if (!user) {
270
+ throw new Error(`JID decoded but user is empty: "${jid}" -> user: "${user}", server: "${server}", device: ${device}`);
271
+ }
272
+ // LID addresses get _1 suffix for Signal protocol
273
+ const signalUser = server === 'lid' ? `${user}_1` : user;
274
+ const finalDevice = device || 0;
275
+ return new libsignal.ProtocolAddress(signalUser, finalDevice);
116
276
  };
117
277
  const jidToSignalSenderKeyName = (group, user) => {
118
278
  return new sender_key_name_1.SenderKeyName(group, jidToSignalProtocolAddress(user));
119
279
  };
120
- function signalStorage({ creds, keys }) {
280
+ function signalStorage({ creds, keys }, lidMapping) {
121
281
  return {
122
282
  loadSession: async (id) => {
123
- const { [id]: sess } = await keys.get('session', [id]);
124
- if (sess) {
125
- return libsignal.SessionRecord.deserialize(sess);
283
+ try {
284
+ // LID SINGLE SOURCE OF TRUTH: Auto-redirect PN to LID if mapping exists
285
+ let actualId = id;
286
+ if (id.includes('.') && !id.includes('_1')) {
287
+ // This is a PN signal address format (e.g., "1234567890.0")
288
+ // Convert back to JID to check for LID mapping
289
+ const parts = id.split('.');
290
+ const device = parts[1] || '0';
291
+ const pnJid = device === '0' ? `${parts[0]}@s.whatsapp.net` : `${parts[0]}:${device}@s.whatsapp.net`;
292
+ const lidForPN = await lidMapping.getLIDForPN(pnJid);
293
+ if (lidForPN?.includes('@lid')) {
294
+ const lidAddr = jidToSignalProtocolAddress(lidForPN);
295
+ const lidId = lidAddr.toString();
296
+ // Check if LID session exists
297
+ const { [lidId]: lidSession } = await keys.get('session', [lidId]);
298
+ if (lidSession) {
299
+ actualId = lidId;
300
+ }
301
+ }
302
+ }
303
+ const { [actualId]: sess } = await keys.get('session', [actualId]);
304
+ if (sess) {
305
+ return libsignal.SessionRecord.deserialize(sess);
306
+ }
307
+ }
308
+ catch (e) {
309
+ return null;
126
310
  }
311
+ return null;
127
312
  },
128
313
  storeSession: async (id, session) => {
129
314
  await keys.set({ session: { [id]: session.serialize() } });
@@ -167,7 +352,7 @@ function signalStorage({ creds, keys }) {
167
352
  const { signedIdentityKey } = creds;
168
353
  return {
169
354
  privKey: Buffer.from(signedIdentityKey.private),
170
- pubKey: (0, Utils_1.generateSignalPubKey)(signedIdentityKey.public)
355
+ pubKey: Buffer.from((0, Utils_1.generateSignalPubKey)(signedIdentityKey.public))
171
356
  };
172
357
  }
173
358
  };
@@ -0,0 +1,26 @@
1
+ import type { SignalKeyStoreWithTransaction } from '../Types';
2
+ export declare class LIDMappingStore {
3
+ private readonly mappingCache;
4
+ private readonly keys;
5
+ private onWhatsAppFunc?;
6
+ constructor(keys: SignalKeyStoreWithTransaction, onWhatsAppFunc?: (...jids: string[]) => Promise<{
7
+ jid: string;
8
+ exists: boolean;
9
+ lid: string;
10
+ }[] | undefined>);
11
+ /**
12
+ * Store LID-PN mapping - USER LEVEL
13
+ */
14
+ storeLIDPNMappings(pairs: {
15
+ lid: string;
16
+ pn: string;
17
+ }[]): Promise<void>;
18
+ /**
19
+ * Get LID for PN - Returns device-specific LID based on user mapping
20
+ */
21
+ getLIDForPN(pn: string): Promise<string | null>;
22
+ /**
23
+ * Get PN for LID - USER LEVEL with device construction
24
+ */
25
+ getPNForLID(lid: string): Promise<string | null>;
26
+ }
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LIDMappingStore = void 0;
7
+ const lru_cache_1 = require("lru-cache");
8
+ const logger_1 = __importDefault(require("../Utils/logger"));
9
+ const WABinary_1 = require("../WABinary");
10
+ class LIDMappingStore {
11
+ constructor(keys, onWhatsAppFunc) {
12
+ this.mappingCache = new lru_cache_1.LRUCache({
13
+ ttl: 7 * 24 * 60 * 60 * 1000, // 7 days
14
+ ttlAutopurge: true,
15
+ updateAgeOnGet: true
16
+ });
17
+ this.keys = keys;
18
+ this.onWhatsAppFunc = onWhatsAppFunc; // needed to get LID from PN if not found
19
+ }
20
+ /**
21
+ * Store LID-PN mapping - USER LEVEL
22
+ */
23
+ async storeLIDPNMappings(pairs) {
24
+ // Validate inputs
25
+ const pairMap = {};
26
+ for (const { lid, pn } of pairs) {
27
+ if (!(((0, WABinary_1.isLidUser)(lid) && (0, WABinary_1.isPnUser)(pn)) || ((0, WABinary_1.isPnUser)(lid) && (0, WABinary_1.isLidUser)(pn)))) {
28
+ logger_1.default.warn(`Invalid LID-PN mapping: ${lid}, ${pn}`);
29
+ continue;
30
+ }
31
+ const [lidJid, pnJid] = (0, WABinary_1.isLidUser)(lid) ? [lid, pn] : [pn, lid];
32
+ const lidDecoded = (0, WABinary_1.jidDecode)(lidJid);
33
+ const pnDecoded = (0, WABinary_1.jidDecode)(pnJid);
34
+ if (!lidDecoded || !pnDecoded)
35
+ return;
36
+ const pnUser = pnDecoded.user;
37
+ const lidUser = lidDecoded.user;
38
+ // Check if mapping already exists (cache first, then database)
39
+ let existingLidUser = this.mappingCache.get(`pn:${pnUser}`);
40
+ if (!existingLidUser) {
41
+ // Cache miss - check database
42
+ const stored = await this.keys.get('lid-mapping', [pnUser]);
43
+ existingLidUser = stored[pnUser];
44
+ if (existingLidUser) {
45
+ // Update cache with database value
46
+ this.mappingCache.set(`pn:${pnUser}`, existingLidUser);
47
+ this.mappingCache.set(`lid:${existingLidUser}`, pnUser);
48
+ }
49
+ }
50
+ if (existingLidUser === lidUser) {
51
+ logger_1.default.debug({ pnUser, lidUser }, 'LID mapping already exists, skipping');
52
+ continue;
53
+ }
54
+ pairMap[pnUser] = lidUser;
55
+ }
56
+ logger_1.default.trace({ pairMap }, `Storing ${Object.keys(pairMap).length} pn mappings`);
57
+ await this.keys.transaction(async () => {
58
+ for (const [pnUser, lidUser] of Object.entries(pairMap)) {
59
+ await this.keys.set({
60
+ 'lid-mapping': {
61
+ [pnUser]: lidUser, // "554396160286" -> "102765716062358"
62
+ [`${lidUser}_reverse`]: pnUser // "102765716062358_reverse" -> "554396160286"
63
+ }
64
+ });
65
+ // Update cache with both directions
66
+ this.mappingCache.set(`pn:${pnUser}`, lidUser);
67
+ this.mappingCache.set(`lid:${lidUser}`, pnUser);
68
+ }
69
+ }, 'lid-mapping');
70
+ }
71
+ /**
72
+ * Get LID for PN - Returns device-specific LID based on user mapping
73
+ */
74
+ async getLIDForPN(pn) {
75
+ if (!(0, WABinary_1.isPnUser)(pn))
76
+ return null;
77
+ const decoded = (0, WABinary_1.jidDecode)(pn);
78
+ if (!decoded)
79
+ return null;
80
+ // Check cache first for PN → LID mapping
81
+ const pnUser = decoded.user;
82
+ let lidUser = this.mappingCache.get(`pn:${pnUser}`);
83
+ if (!lidUser) {
84
+ // Cache miss - check database
85
+ const stored = await this.keys.get('lid-mapping', [pnUser]);
86
+ lidUser = stored[pnUser];
87
+ if (lidUser) {
88
+ // Cache the database result
89
+ this.mappingCache.set(`pn:${pnUser}`, lidUser);
90
+ }
91
+ else {
92
+ // Not in database - try USync
93
+ logger_1.default.trace(`No LID mapping found for PN user ${pnUser}; getting from USync`);
94
+ const { exists, lid } = (await this.onWhatsAppFunc?.(pn))?.[0]; // this function already adds LIDs to mapping
95
+ if (exists && lid) {
96
+ lidUser = (0, WABinary_1.jidDecode)(lid)?.user;
97
+ if (lidUser) {
98
+ // Cache the USync result
99
+ this.mappingCache.set(`pn:${pnUser}`, lidUser);
100
+ }
101
+ }
102
+ else {
103
+ return null;
104
+ }
105
+ }
106
+ }
107
+ if (typeof lidUser !== 'string' || !lidUser) {
108
+ logger_1.default.warn(`Invalid or empty LID user for PN ${pn}: lidUser = "${lidUser}"`);
109
+ return null;
110
+ }
111
+ // Push the PN device ID to the LID to maintain device separation
112
+ const pnDevice = decoded.device !== undefined ? decoded.device : 0;
113
+ const deviceSpecificLid = `${lidUser}:${pnDevice}@lid`;
114
+ logger_1.default.trace(`getLIDForPN: ${pn} → ${deviceSpecificLid} (user mapping with device ${pnDevice})`);
115
+ return deviceSpecificLid;
116
+ }
117
+ /**
118
+ * Get PN for LID - USER LEVEL with device construction
119
+ */
120
+ async getPNForLID(lid) {
121
+ if (!(0, WABinary_1.isLidUser)(lid))
122
+ return null;
123
+ const decoded = (0, WABinary_1.jidDecode)(lid);
124
+ if (!decoded)
125
+ return null;
126
+ // Check cache first for LID → PN mapping
127
+ const lidUser = decoded.user;
128
+ let pnUser = this.mappingCache.get(`lid:${lidUser}`);
129
+ if (!pnUser || typeof pnUser !== 'string') {
130
+ // Cache miss - check database
131
+ const stored = await this.keys.get('lid-mapping', [`${lidUser}_reverse`]);
132
+ pnUser = stored[`${lidUser}_reverse`];
133
+ if (!pnUser || typeof pnUser !== 'string') {
134
+ logger_1.default.trace(`No reverse mapping found for LID user: ${lidUser}`);
135
+ return null;
136
+ }
137
+ this.mappingCache.set(`lid:${lidUser}`, pnUser);
138
+ }
139
+ // Construct device-specific PN JID
140
+ const lidDevice = decoded.device !== undefined ? decoded.device : 0;
141
+ const pnJid = `${pnUser}:${lidDevice}@s.whatsapp.net`;
142
+ logger_1.default.trace(`Found reverse mapping: ${lid} → ${pnJid}`);
143
+ return pnJid;
144
+ }
145
+ }
146
+ exports.LIDMappingStore = LIDMappingStore;
@@ -1,3 +1,2 @@
1
- export * from './abstract-socket-client';
2
- export * from './mobile-socket-client';
3
- export * from './web-socket-client';
1
+ export * from './types';
2
+ export * from './websocket';
@@ -14,6 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./abstract-socket-client"), exports);
18
- __exportStar(require("./mobile-socket-client"), exports);
19
- __exportStar(require("./web-socket-client"), exports);
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./websocket"), exports);
@@ -1,8 +1,6 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
1
  import { EventEmitter } from 'events';
4
2
  import { URL } from 'url';
5
- import { SocketConfig } from '../../Types';
3
+ import type { SocketConfig } from '../../Types';
6
4
  export declare abstract class AbstractSocketClient extends EventEmitter {
7
5
  url: URL;
8
6
  config: SocketConfig;
@@ -1,5 +1,5 @@
1
1
  import WebSocket from 'ws';
2
- import { AbstractSocketClient } from './abstract-socket-client';
2
+ import { AbstractSocketClient } from './types';
3
3
  export declare class WebSocketClient extends AbstractSocketClient {
4
4
  protected socket: WebSocket | null;
5
5
  get isOpen(): boolean;
@@ -6,44 +6,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.WebSocketClient = void 0;
7
7
  const ws_1 = __importDefault(require("ws"));
8
8
  const Defaults_1 = require("../../Defaults");
9
- const abstract_socket_client_1 = require("./abstract-socket-client");
10
- class WebSocketClient extends abstract_socket_client_1.AbstractSocketClient {
9
+ const types_1 = require("./types");
10
+ class WebSocketClient extends types_1.AbstractSocketClient {
11
11
  constructor() {
12
12
  super(...arguments);
13
13
  this.socket = null;
14
14
  }
15
15
  get isOpen() {
16
- var _a;
17
- return ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === ws_1.default.OPEN;
16
+ return this.socket?.readyState === ws_1.default.OPEN;
18
17
  }
19
18
  get isClosed() {
20
- var _a;
21
- return this.socket === null || ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === ws_1.default.CLOSED;
19
+ return this.socket === null || this.socket?.readyState === ws_1.default.CLOSED;
22
20
  }
23
21
  get isClosing() {
24
- var _a;
25
- return this.socket === null || ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === ws_1.default.CLOSING;
22
+ return this.socket === null || this.socket?.readyState === ws_1.default.CLOSING;
26
23
  }
27
24
  get isConnecting() {
28
- var _a;
29
- return ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.readyState) === ws_1.default.CONNECTING;
25
+ return this.socket?.readyState === ws_1.default.CONNECTING;
30
26
  }
31
27
  async connect() {
32
- var _a, _b;
33
28
  if (this.socket) {
34
29
  return;
35
30
  }
36
31
  this.socket = new ws_1.default(this.url, {
37
32
  origin: Defaults_1.DEFAULT_ORIGIN,
38
- headers: (_a = this.config.options) === null || _a === void 0 ? void 0 : _a.headers,
33
+ headers: this.config.options?.headers,
39
34
  handshakeTimeout: this.config.connectTimeoutMs,
40
35
  timeout: this.config.connectTimeoutMs,
41
- agent: this.config.agent,
36
+ agent: this.config.agent
42
37
  });
43
38
  this.socket.setMaxListeners(0);
44
39
  const events = ['close', 'error', 'upgrade', 'message', 'open', 'ping', 'pong', 'unexpected-response'];
45
40
  for (const event of events) {
46
- (_b = this.socket) === null || _b === void 0 ? void 0 : _b.on(event, (...args) => this.emit(event, ...args));
41
+ this.socket?.on(event, (...args) => this.emit(event, ...args));
47
42
  }
48
43
  }
49
44
  async close() {
@@ -54,8 +49,7 @@ class WebSocketClient extends abstract_socket_client_1.AbstractSocketClient {
54
49
  this.socket = null;
55
50
  }
56
51
  send(str, cb) {
57
- var _a;
58
- (_a = this.socket) === null || _a === void 0 ? void 0 : _a.send(str, cb);
52
+ this.socket?.send(str, cb);
59
53
  return Boolean(this.socket);
60
54
  }
61
55
  }