kage-baileys 3.0.6 → 3.2.3

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 (216) hide show
  1. package/Example/connection.cjs +4 -0
  2. package/README.MD +4726 -48
  3. package/WAProto/WAProto.proto +3395 -415
  4. package/WAProto/compat.cjs +12 -0
  5. package/WAProto/index.d.ts +47104 -19888
  6. package/WAProto/index.js +131979 -57361
  7. package/lib/Addon/http-error.js +43 -0
  8. package/lib/Addon/index.js +32 -0
  9. package/lib/Addon/keyed-db.js +250 -0
  10. package/lib/Addon/link-preview.js +82 -0
  11. package/lib/Defaults/baileys-version.json +3 -0
  12. package/lib/Defaults/connection.js +110 -0
  13. package/lib/Defaults/constants.js +156 -0
  14. package/lib/Defaults/history.js +46 -0
  15. package/lib/Defaults/index.js +230 -0
  16. package/lib/Defaults/media.js +104 -0
  17. package/lib/Defaults/phonenumber-mcc.json +223 -0
  18. package/lib/Defaults/prefix.js +44 -0
  19. package/lib/Extensions/business-advanced.js +382 -0
  20. package/lib/Extensions/business.js +159 -0
  21. package/lib/Extensions/chats-advanced.js +1106 -0
  22. package/lib/Extensions/chats.js +349 -0
  23. package/lib/Extensions/communities-advanced.js +430 -0
  24. package/lib/Extensions/community.js +94 -0
  25. package/lib/Extensions/groups-advanced.js +343 -0
  26. package/lib/Extensions/index.js +30 -0
  27. package/lib/Extensions/messages-recv-advanced.js +1690 -0
  28. package/lib/Extensions/messages-send-advanced.js +622 -0
  29. package/lib/Extensions/messages-send.js +1380 -0
  30. package/lib/Extensions/newsletter-advanced.js +228 -0
  31. package/lib/Extensions/newsletter.js +72 -0
  32. package/lib/Extensions/socket.js +389 -0
  33. package/lib/Modded/message_builder.js +2084 -4
  34. package/lib/Signal/Group/ciphertext-message.js +54 -0
  35. package/lib/Signal/Group/group-session-builder.js +124 -0
  36. package/lib/Signal/Group/group_cipher.js +216 -0
  37. package/lib/Signal/Group/index.js +124 -0
  38. package/lib/Signal/Group/keyhelper.js +108 -0
  39. package/lib/Signal/Group/sender-chain-key.js +83 -0
  40. package/lib/Signal/Group/sender-key-distribution-message.js +157 -0
  41. package/lib/Signal/Group/sender-key-message.js +166 -0
  42. package/lib/Signal/Group/sender-key-name.js +130 -0
  43. package/lib/Signal/Group/sender-key-record.js +113 -0
  44. package/lib/Signal/Group/sender-key-state.js +208 -0
  45. package/lib/Signal/Group/sender-message-key.js +82 -0
  46. package/lib/Signal/libsignal.js +935 -0
  47. package/lib/Signal/lid-mapping.js +545 -1
  48. package/lib/Socket/Client/index.js +60 -0
  49. package/lib/Socket/Client/types.js +51 -0
  50. package/lib/Socket/Client/websocket.js +152 -0
  51. package/lib/Socket/business.js +831 -0
  52. package/lib/Socket/chats.js +2535 -49
  53. package/lib/Socket/communities.js +450 -1
  54. package/lib/Socket/community.js +1022 -0
  55. package/lib/Socket/dugong.js +1 -1
  56. package/lib/Socket/groups.js +747 -0
  57. package/lib/Socket/index.js +60 -2
  58. package/lib/Socket/messages-recv.js +3450 -5
  59. package/lib/Socket/messages-send.js +3123 -0
  60. package/lib/Socket/mex.js +126 -1
  61. package/lib/Socket/newsletter.js +465 -0
  62. package/lib/Socket/socket.js +2217 -1
  63. package/lib/Store/index.js +79 -0
  64. package/lib/Store/make-cache-manager-store.js +186 -0
  65. package/lib/Store/make-in-memory-store.js +878 -0
  66. package/lib/Store/make-ordered-dictionary.js +187 -0
  67. package/lib/Store/object-repository.js +78 -0
  68. package/lib/Types/Auth.js +25 -0
  69. package/lib/Types/Bussines.js +25 -1
  70. package/lib/Types/Call.js +25 -0
  71. package/lib/Types/Chat.js +39 -0
  72. package/lib/Types/Contact.js +25 -0
  73. package/lib/Types/Events.js +25 -0
  74. package/lib/Types/GroupMetadata.js +25 -0
  75. package/lib/Types/Label.js +76 -0
  76. package/lib/Types/LabelAssociation.js +40 -0
  77. package/lib/Types/Message.js +57 -0
  78. package/lib/Types/Mex.js +56 -1
  79. package/lib/Types/MexUpdates.js +46 -0
  80. package/lib/Types/Newsletter.js +56 -0
  81. package/lib/Types/Product.js +25 -0
  82. package/lib/Types/RichType.js +23 -0
  83. package/lib/Types/Signal.js +25 -0
  84. package/lib/Types/Socket.js +25 -0
  85. package/lib/Types/State.js +92 -0
  86. package/lib/Types/USync.js +25 -0
  87. package/lib/Types/index.js +133 -0
  88. package/lib/Utils/auth-utils.js +703 -0
  89. package/lib/Utils/automation-tools.js +51 -16
  90. package/lib/Utils/baileys-event-stream.js +146 -0
  91. package/lib/Utils/browser-utils.js +95 -0
  92. package/lib/Utils/business.js +525 -0
  93. package/lib/Utils/chat-utils.js +1861 -0
  94. package/lib/Utils/companion-reg-client-utils.js +55 -1
  95. package/lib/Utils/crypto.js +355 -0
  96. package/lib/Utils/decode-wa-message.js +709 -0
  97. package/lib/Utils/event-buffer.js +1323 -8
  98. package/lib/Utils/generics.js +945 -1
  99. package/lib/Utils/history.js +266 -0
  100. package/lib/Utils/identity-change-handler.js +62 -1
  101. package/lib/Utils/index.js +114 -0
  102. package/lib/Utils/link-preview.js +179 -0
  103. package/lib/Utils/logger.js +42 -0
  104. package/lib/Utils/lt-hash.js +73 -0
  105. package/lib/Utils/make-mutex.js +104 -0
  106. package/lib/Utils/message-inspector.js +110 -0
  107. package/lib/Utils/message-retry-manager.js +507 -2
  108. package/lib/Utils/messages-media.js +1931 -1
  109. package/lib/Utils/messages.js +3748 -0
  110. package/lib/Utils/noise-handler.js +423 -0
  111. package/lib/Utils/offline-node-processor.js +53 -1
  112. package/lib/Utils/pre-key-manager.js +255 -1
  113. package/lib/Utils/process-message.js +1592 -0
  114. package/lib/Utils/reporting-utils.js +272 -1
  115. package/lib/Utils/rich-message-utils.js +377 -0
  116. package/lib/Utils/rich-messages.js +1 -1
  117. package/lib/Utils/signal.js +437 -0
  118. package/lib/Utils/stanza-ack.js +51 -1
  119. package/lib/Utils/status-refresh.js +37 -0
  120. package/lib/Utils/status-tools.js +4 -2
  121. package/lib/Utils/sync-action-utils.js +63 -1
  122. package/lib/Utils/tc-token-utils.js +185 -1
  123. package/lib/Utils/terminal-banner.js +31 -0
  124. package/lib/Utils/use-multi-file-auth-state.js +271 -0
  125. package/lib/Utils/use-single-file-auth-state.js +108 -0
  126. package/lib/Utils/use-sqlite-auth-state.js +142 -0
  127. package/lib/Utils/validate-connection.js +497 -1
  128. package/lib/Utils/view-once-compat.js +13 -5
  129. package/lib/VoIP/audio-feeder.js +150 -0
  130. package/lib/VoIP/index.js +289 -0
  131. package/lib/VoIP/relay-transport.js +608 -0
  132. package/lib/VoIP/signaling.js +583 -0
  133. package/lib/VoIP/types.js +30 -0
  134. package/lib/VoIP/wasm-engine.js +1261 -2
  135. package/lib/VoIP/worker-bootstrap.js +1090 -2
  136. package/lib/WABinary/constants.js +2805 -0
  137. package/lib/WABinary/decode.js +649 -2
  138. package/lib/WABinary/encode.js +564 -2
  139. package/lib/WABinary/generic-utils.js +401 -0
  140. package/lib/WABinary/index.js +82 -0
  141. package/lib/WABinary/jid-utils.js +290 -0
  142. package/lib/WABinary/types.js +25 -0
  143. package/lib/WAM/BinaryInfo.js +50 -0
  144. package/lib/WAM/constants.js +45747 -0
  145. package/lib/WAM/encode.js +393 -0
  146. package/lib/WAM/index.js +78 -0
  147. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +135 -0
  148. package/lib/WAUSync/Protocols/USyncContactProtocol.js +110 -0
  149. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +142 -0
  150. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +85 -0
  151. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +69 -0
  152. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +107 -0
  153. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +38 -1
  154. package/lib/WAUSync/Protocols/index.js +83 -0
  155. package/lib/WAUSync/USyncQuery.js +241 -2
  156. package/lib/WAUSync/USyncUser.js +86 -0
  157. package/lib/WAUSync/index.js +78 -0
  158. package/lib/assets/wasm/loader.js +1875 -1
  159. package/lib/assets/wasm/worker-modules.js +11047 -1
  160. package/lib/index.d.ts +126 -0
  161. package/lib/index.js +53 -21
  162. package/lib/index.mjs +437 -0
  163. package/licenses/upstream-MIT.txt +22 -0
  164. package/maintenance/api-coverage.json +1642 -0
  165. package/maintenance/archivos-sha256.json +207 -0
  166. package/maintenance/consumer-validation.log +3 -0
  167. package/maintenance/dependency-audit.json +4 -4
  168. package/maintenance/extension-inventory.json +57 -0
  169. package/maintenance/protocol-update.json +1101 -0
  170. package/maintenance/protocol-wire-audit.json +4 -0
  171. package/maintenance/reference-socket-surface.json +209 -0
  172. package/maintenance/resumen-validacion.json +50 -0
  173. package/maintenance/validation.log +2725 -0
  174. package/maintenance/verification.json +566 -0
  175. package/package.json +107 -9
  176. package/scripts/check-imports.cjs +10 -0
  177. package/scripts/check-package.cjs +40 -0
  178. package/scripts/check-syntax.cjs +1 -1
  179. package/scripts/generate-protobuf.cjs +6 -1
  180. package/scripts/generate-public-types.cjs +9 -0
  181. package/scripts/kage-base64-fix.cjs +45 -0
  182. package/scripts/maintenance.cjs +10 -0
  183. package/test/advanced.test.cjs +24 -0
  184. package/test/base64-fix.test.cjs +49 -0
  185. package/test/maintenance.test.cjs +1 -1
  186. package/test/npm-publication.test.cjs +141 -0
  187. package/test/recepcion-reparada.test.cjs +98 -0
  188. package/test/resilience-binary.test.cjs +69 -0
  189. package/test/resilience-transport.test.cjs +34 -0
  190. package/test/types.test.ts +5 -0
  191. package/test/upgrade.test.cjs +104 -0
  192. package/tsconfig.json +20 -0
  193. package/WAProto/p.html +0 -1
  194. package/lib/KageExtra/Modded/message_builder.js +0 -2330
  195. package/lib/KageExtra/VoIP/audio-feeder.js +0 -136
  196. package/lib/KageExtra/VoIP/index.js +0 -282
  197. package/lib/KageExtra/VoIP/relay-transport.js +0 -559
  198. package/lib/KageExtra/VoIP/signaling.js +0 -603
  199. package/lib/KageExtra/VoIP/types.js +0 -17
  200. package/lib/KageExtra/VoIP/wasm-engine.js +0 -1214
  201. package/lib/KageExtra/VoIP/worker-bootstrap.js +0 -1042
  202. package/lib/KageExtra/assets/wasm/loader.js +0 -5
  203. package/lib/KageExtra/assets/wasm/whatsapp.wasm +0 -0
  204. package/lib/KageExtra/assets/wasm/worker-modules.js +0 -273
  205. package/lib/KageExtra/index.js +0 -3
  206. package/lib/KageExtra/package.json +0 -1
  207. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +0 -53
  208. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +0 -24
  209. package/maintenance/revision-full-check.txt +0 -1097
  210. package/maintenance/revision-library-tests.tap +0 -1088
  211. package/maintenance/revision-protobuf.txt +0 -5
  212. package/maintenance/revision-syntax.txt +0 -5
  213. package/maintenance/schema-coverage.json +0 -23
  214. package/maintenance/schema-merge.json +0 -30
  215. package/maintenance/validation-node20.txt +0 -191
  216. package/maintenance/validation-node22.txt +0 -237
@@ -182,3 +182,938 @@ function signalStorage({ creds, keys }) {
182
182
  }
183
183
  };
184
184
  }
185
+
186
+ // Kage: compatibilidad de API.
187
+ const __kageModule19 = (() => {
188
+ const module = { exports: {} }; const exports = module.exports;
189
+ "use strict"
190
+
191
+ Object.defineProperty(exports, "__esModule", { value: true })
192
+
193
+ const {
194
+ SessionCipher,
195
+ SessionBuilder,
196
+ SessionRecord,
197
+ ProtocolAddress
198
+ } = require("@itsukichan/libsignal-node")
199
+ const { generateSignalPubKey } = require("../Utils")
200
+ const {
201
+ isHostedLidUser,
202
+ isHostedPnUser,
203
+ isLidUser,
204
+ isPnUser,
205
+ jidDecode,
206
+ transferDevice,
207
+ WAJIDDomains
208
+ } = require("../WABinary")
209
+ const { SenderKeyName } = require("./Group/sender-key-name")
210
+ const { SenderKeyRecord } = require("./Group/sender-key-record")
211
+ const {
212
+ GroupCipher,
213
+ GroupSessionBuilder,
214
+ SenderKeyDistributionMessage
215
+ } = require("./Group")
216
+ const { LRUCache } = require("lru-cache")
217
+ const { LIDMappingStore } = require("./lid-mapping")
218
+
219
+ function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
220
+ const lidMapping = new LIDMappingStore(auth.keys, logger, pnToLIDFunc)
221
+ const storage = signalStorage(auth, lidMapping)
222
+ const parsedKeys = auth.keys
223
+ const migratedSessionCache = new LRUCache({
224
+ ttl: 3 * 24 * 60 * 60 * 1000, // 7 days
225
+ ttlAutopurge: true,
226
+ updateAgeOnGet: true
227
+ })
228
+
229
+ const repository = {
230
+ decryptGroupMessage({ group, authorJid, msg }) {
231
+ const senderName = jidToSignalSenderKeyName(group, authorJid)
232
+ const cipher = new GroupCipher(storage, senderName)
233
+
234
+ // Use transaction to ensure atomicity
235
+ return parsedKeys.transaction(async () => {
236
+ return cipher.decrypt(msg)
237
+ }, group)
238
+ },
239
+
240
+ async processSenderKeyDistributionMessage({ item, authorJid }) {
241
+ const builder = new GroupSessionBuilder(storage)
242
+
243
+ if (!item.groupId) {
244
+ throw new Error('Group ID is required for sender key distribution message')
245
+ }
246
+
247
+ const senderName = jidToSignalSenderKeyName(item.groupId, authorJid)
248
+ const senderMsg = new SenderKeyDistributionMessage(null, null, null, null, item.axolotlSenderKeyDistributionMessage)
249
+ const senderNameStr = senderName.toString()
250
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr])
251
+
252
+ if (!senderKey) {
253
+ await storage.storeSenderKey(senderName, new SenderKeyRecord())
254
+ }
255
+
256
+ return parsedKeys.transaction(async () => {
257
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr])
258
+
259
+ if (!senderKey) {
260
+ await storage.storeSenderKey(senderName, new SenderKeyRecord())
261
+ }
262
+
263
+ await builder.process(senderName, senderMsg)
264
+ }, item.groupId)
265
+ },
266
+
267
+ async decryptMessage({ jid, type, ciphertext }) {
268
+ const addr = jidToSignalProtocolAddress(jid)
269
+ const session = new SessionCipher(storage, addr)
270
+
271
+ async function doDecrypt() {
272
+ let result
273
+
274
+ switch (type) {
275
+ case 'pkmsg':
276
+ result = await session.decryptPreKeyWhisperMessage(ciphertext)
277
+ break
278
+ case 'msg':
279
+ result = await session.decryptWhisperMessage(ciphertext)
280
+ break
281
+ }
282
+
283
+ return result
284
+ }
285
+
286
+ // If it's not a sync message, we need to ensure atomicity
287
+ // For regular messages, we use a transaction to ensure atomicity
288
+ return parsedKeys.transaction(async () => {
289
+ return await doDecrypt()
290
+ }, jid)
291
+ },
292
+
293
+ async encryptMessage({ jid, data }) {
294
+ const addr = jidToSignalProtocolAddress(jid)
295
+ const cipher = new SessionCipher(storage, addr)
296
+
297
+ // Use transaction to ensure atomicity
298
+ return parsedKeys.transaction(async () => {
299
+ const { type: sigType, body } = await cipher.encrypt(data)
300
+ const type = sigType === 3 ? 'pkmsg' : 'msg'
301
+
302
+ return { type, ciphertext: Buffer.from(body, 'binary') }
303
+ }, jid)
304
+ },
305
+
306
+ async encryptGroupMessage({ group, meId, data }) {
307
+ const senderName = jidToSignalSenderKeyName(group, meId)
308
+ const builder = new GroupSessionBuilder(storage)
309
+ const senderNameStr = senderName.toString()
310
+
311
+ return parsedKeys.transaction(async () => {
312
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr])
313
+
314
+ if (!senderKey) {
315
+ await storage.storeSenderKey(senderName, new SenderKeyRecord())
316
+ }
317
+
318
+ const senderKeyDistributionMessage = await builder.create(senderName)
319
+ const session = new GroupCipher(storage, senderName)
320
+ const ciphertext = await session.encrypt(data)
321
+
322
+ return {
323
+ ciphertext,
324
+ senderKeyDistributionMessage: senderKeyDistributionMessage.serialize()
325
+ }
326
+ }, group)
327
+ },
328
+
329
+ async injectE2ESession({ jid, session }) {
330
+ logger.trace({ jid }, 'injecting E2EE session')
331
+
332
+ const cipher = new SessionBuilder(storage, jidToSignalProtocolAddress(jid))
333
+
334
+ return parsedKeys.transaction(async () => {
335
+ await cipher.initOutgoing(session)
336
+ }, jid)
337
+ },
338
+
339
+ jidToSignalProtocolAddress(jid) {
340
+ return jidToSignalProtocolAddress(jid).toString()
341
+ },
342
+
343
+ // Optimized direct access to LID mapping store
344
+ lidMapping,
345
+
346
+ async validateSession(jid) {
347
+ try {
348
+ const addr = jidToSignalProtocolAddress(jid)
349
+ const session = await storage.loadSession(addr.toString())
350
+
351
+ if (!session) {
352
+ return { exists: false, reason: 'no session' }
353
+ }
354
+
355
+ if (!session.haveOpenSession()) {
356
+ return { exists: false, reason: 'no open session' }
357
+ }
358
+
359
+ return { exists: true }
360
+ }
361
+
362
+ catch (error) {
363
+ return { exists: false, reason: 'validation error' }
364
+ }
365
+ },
366
+
367
+ async deleteSession(jids) {
368
+ if (!jids.length) return
369
+
370
+ // Convert JIDs to signal addresses and prepare for bulk deletion
371
+ const sessionUpdates = {}
372
+
373
+ jids.forEach(jid => {
374
+ const addr = jidToSignalProtocolAddress(jid)
375
+ sessionUpdates[addr.toString()] = null
376
+ })
377
+
378
+ // Single transaction for all deletions
379
+ return parsedKeys.transaction(async () => {
380
+ await auth.keys.set({ session: sessionUpdates })
381
+ }, `delete-${jids.length}-sessions`)
382
+ },
383
+
384
+ async migrateSession(fromJid, toJid) {
385
+ // TODO: use usync to handle this entire mess
386
+ if (!fromJid || (!isLidUser(toJid) && !isHostedLidUser(toJid))) {
387
+ return { migrated: 0, skipped: 0, total: 0 }
388
+ }
389
+
390
+ // Only support PN to LID migration
391
+ if (!isPnUser(fromJid) && !isHostedPnUser(fromJid)) {
392
+ return { migrated: 0, skipped: 0, total: 1 }
393
+ }
394
+
395
+ const { user } = jidDecode(fromJid)
396
+
397
+ logger.debug({ fromJid }, 'bulk device migration - loading all user devices')
398
+
399
+ // Get user's device list from storage
400
+ const { [user]: userDevices } = await parsedKeys.get('device-list', [user])
401
+
402
+ if (!userDevices) {
403
+ return { migrated: 0, skipped: 0, total: 0 }
404
+ }
405
+
406
+ const { device: fromDevice } = jidDecode(fromJid)
407
+ const fromDeviceStr = fromDevice?.toString() || '0'
408
+
409
+ if (!userDevices.includes(fromDeviceStr)) {
410
+ userDevices.push(fromDeviceStr)
411
+ }
412
+
413
+ // Filter out cached devices before database fetch
414
+ const uncachedDevices = userDevices.filter(device => {
415
+ const deviceKey = `${user}.${device}`
416
+ return !migratedSessionCache.has(deviceKey)
417
+ })
418
+
419
+ // Bulk check session existence only for uncached devices
420
+ const deviceSessionKeys = uncachedDevices.map(device => `${user}.${device}`)
421
+ const existingSessions = await parsedKeys.get('session', deviceSessionKeys)
422
+
423
+ // Step 3: Convert existing sessions to JIDs (only migrate sessions that exist)
424
+ const deviceJids = []
425
+
426
+ for (const [sessionKey, sessionData] of Object.entries(existingSessions)) {
427
+ if (sessionData) {
428
+ // Session exists in storage
429
+ const deviceStr = sessionKey.split('.')[1]
430
+
431
+ if (!deviceStr) continue
432
+
433
+ const deviceNum = parseInt(deviceStr)
434
+
435
+ let jid = deviceNum === 0 ? `${user}@s.whatsapp.net` : `${user}:${deviceNum}@s.whatsapp.net`
436
+
437
+ if (deviceNum === 99) {
438
+ jid = `${user}:99@hosted`
439
+ }
440
+
441
+ deviceJids.push(jid)
442
+ }
443
+ }
444
+
445
+ logger.debug({
446
+ fromJid,
447
+ totalDevices: userDevices.length,
448
+ devicesWithSessions: deviceJids.length,
449
+ devices: deviceJids
450
+ }, 'bulk device migration complete - all user devices processed')
451
+
452
+ // Single transaction for all migrations
453
+ return parsedKeys.transaction(async () => {
454
+ const migrationOps = deviceJids.map(jid => {
455
+ const lidWithDevice = transferDevice(jid, toJid)
456
+ const fromDecoded = jidDecode(jid)
457
+ const toDecoded = jidDecode(lidWithDevice)
458
+
459
+ return {
460
+ fromJid: jid,
461
+ toJid: lidWithDevice,
462
+ pnUser: fromDecoded.user,
463
+ lidUser: toDecoded.user,
464
+ deviceId: fromDecoded.device || 0,
465
+ fromAddr: jidToSignalProtocolAddress(jid),
466
+ toAddr: jidToSignalProtocolAddress(lidWithDevice)
467
+ }
468
+ })
469
+
470
+ const totalOps = migrationOps.length
471
+
472
+ let migratedCount = 0
473
+
474
+ // Bulk fetch PN sessions - already exist (verified during device discovery)
475
+ const pnAddrStrings = Array.from(new Set(migrationOps.map(op => op.fromAddr.toString())))
476
+ const pnSessions = await parsedKeys.get('session', pnAddrStrings)
477
+
478
+ // Prepare bulk session updates (PN → LID migration + deletion)
479
+ const sessionUpdates = {}
480
+
481
+ for (const op of migrationOps) {
482
+ const pnAddrStr = op.fromAddr.toString()
483
+ const lidAddrStr = op.toAddr.toString()
484
+ const pnSession = pnSessions[pnAddrStr]
485
+
486
+ if (pnSession) {
487
+ // Session exists (guaranteed from device discovery)
488
+ const fromSession = SessionRecord.deserialize(pnSession)
489
+
490
+ if (fromSession.haveOpenSession()) {
491
+ // Queue for bulk update: copy to LID, delete from PN
492
+ sessionUpdates[lidAddrStr] = fromSession.serialize()
493
+ sessionUpdates[pnAddrStr] = null
494
+ migratedCount++
495
+ }
496
+ }
497
+ }
498
+
499
+ // Single bulk session update for all migrations
500
+ if (Object.keys(sessionUpdates).length > 0) {
501
+ await parsedKeys.set({ session: sessionUpdates })
502
+
503
+ logger.debug({ migratedSessions: migratedCount }, 'bulk session migration complete')
504
+
505
+ // Cache device-level migrations
506
+ for (const op of migrationOps) {
507
+ if (sessionUpdates[op.toAddr.toString()]) {
508
+ const deviceKey = `${op.pnUser}.${op.deviceId}`
509
+ migratedSessionCache.set(deviceKey, true)
510
+ }
511
+ }
512
+ }
513
+
514
+ const skippedCount = totalOps - migratedCount
515
+
516
+ return { migrated: migratedCount, skipped: skippedCount, total: totalOps }
517
+ }, `migrate-${deviceJids.length}-sessions-${jidDecode(toJid)?.user}`)
518
+ }
519
+ }
520
+
521
+ return repository
522
+ }
523
+
524
+ const jidToSignalProtocolAddress = (jid) => {
525
+ const decoded = jidDecode(jid)
526
+ const { user, device, server, domainType } = decoded
527
+
528
+ if (!user) {
529
+ throw new Error(`JID decoded but user is empty: "${jid}" -> user: "${user}", server: "${server}", device: ${device}`)
530
+ }
531
+
532
+ const signalUser = domainType !== WAJIDDomains.WHATSAPP ? `${user}_${domainType}` : user
533
+ const finalDevice = device || 0
534
+
535
+ if (device === 99 && decoded.server !== 'hosted' && decoded.server !== 'hosted.lid') {
536
+ throw new Error('Unexpected non-hosted device JID with device 99. This ID seems invalid. ID:' + jid)
537
+ }
538
+
539
+ return new ProtocolAddress(signalUser, finalDevice)
540
+ }
541
+
542
+ const jidToSignalSenderKeyName = (group, user) => {
543
+ return new SenderKeyName(group, jidToSignalProtocolAddress(user))
544
+ }
545
+
546
+ function signalStorage({ creds, keys }, lidMapping) {
547
+ // Shared function to resolve PN signal address to LID if mapping exists
548
+ const resolveLIDSignalAddress = async (id) => {
549
+ if (id.includes('.')) {
550
+ const [deviceId, device] = id.split('.')
551
+ const [user, domainType_] = deviceId.split('_')
552
+ const domainType = parseInt(domainType_ || '0')
553
+
554
+ if (domainType === WAJIDDomains.LID || domainType === WAJIDDomains.HOSTED_LID) return id
555
+
556
+ const pnJid = `${user}${device !== '0' ? `:${device}` : ''}@${domainType === WAJIDDomains.HOSTED ? 'hosted' : 's.whatsapp.net'}`
557
+ const lidForPN = await lidMapping.getLIDForPN(pnJid)
558
+
559
+ if (lidForPN) {
560
+ const lidAddr = jidToSignalProtocolAddress(lidForPN)
561
+ return lidAddr.toString()
562
+ }
563
+ }
564
+
565
+ return id
566
+ }
567
+
568
+ return {
569
+ loadSession: async (id) => {
570
+ try {
571
+ const wireJid = await resolveLIDSignalAddress(id)
572
+ const { [wireJid]: sess } = await keys.get('session', [wireJid])
573
+
574
+ if (sess) {
575
+ return SessionRecord.deserialize(sess)
576
+ }
577
+ }
578
+
579
+ catch (e) {
580
+ return null
581
+ }
582
+
583
+ return null
584
+ },
585
+ storeSession: async (id, session) => {
586
+ const wireJid = await resolveLIDSignalAddress(id)
587
+ await keys.set({ session: { [wireJid]: session.serialize() } })
588
+ },
589
+ isTrustedIdentity: () => {
590
+ return true // todo: implement
591
+ },
592
+ loadPreKey: async (id) => {
593
+ const keyId = id.toString()
594
+ const { [keyId]: key } = await keys.get('pre-key', [keyId])
595
+
596
+ if (key) {
597
+ return {
598
+ privKey: Buffer.from(key.private),
599
+ pubKey: Buffer.from(key.public)
600
+ }
601
+ }
602
+ },
603
+ removePreKey: (id) => keys.set({ 'pre-key': { [id]: null } }),
604
+ loadSignedPreKey: () => {
605
+ const key = creds.signedPreKey
606
+ return {
607
+ privKey: Buffer.from(key.keyPair.private),
608
+ pubKey: Buffer.from(key.keyPair.public)
609
+ }
610
+ },
611
+ loadSenderKey: async (senderKeyName) => {
612
+ const keyId = senderKeyName.toString()
613
+ const { [keyId]: key } = await keys.get('sender-key', [keyId])
614
+
615
+ if (key) {
616
+ return SenderKeyRecord.deserialize(key)
617
+ }
618
+
619
+ return new SenderKeyRecord()
620
+ },
621
+ storeSenderKey: async (senderKeyName, key) => {
622
+ const keyId = senderKeyName.toString()
623
+ const serialized = JSON.stringify(key.serialize())
624
+ await keys.set({ 'sender-key': { [keyId]: Buffer.from(serialized, 'utf-8') } })
625
+ },
626
+ getOurRegistrationId: () => creds.registrationId,
627
+ getOurIdentity: () => {
628
+ const { signedIdentityKey } = creds
629
+ return {
630
+ privKey: Buffer.from(signedIdentityKey.private),
631
+ pubKey: Buffer.from(generateSignalPubKey(signedIdentityKey.public))
632
+ }
633
+ }
634
+ }
635
+ }
636
+
637
+ module.exports = {
638
+ makeLibSignalRepository
639
+ }
640
+ return module.exports;
641
+ })();
642
+ for (const key of Object.keys(__kageModule19)) {
643
+ if (key !== '__esModule' && !Object.prototype.hasOwnProperty.call(exports,key)) Object.defineProperty(exports,key,{enumerable:true,configurable:true,get:()=>__kageModule19[key]});
644
+ }
645
+
646
+ // Kage: funciones avanzadas.
647
+ const __kageModule125 = (() => {
648
+ const module = { exports: {} }; const exports = module.exports;
649
+ "use strict";
650
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
651
+ if (k2 === undefined) k2 = k;
652
+ var desc = Object.getOwnPropertyDescriptor(m, k);
653
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
654
+ desc = { enumerable: true, get: function() { return m[k]; } };
655
+ }
656
+ Object.defineProperty(o, k2, desc);
657
+ }) : (function(o, m, k, k2) {
658
+ if (k2 === undefined) k2 = k;
659
+ o[k2] = m[k];
660
+ }));
661
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
662
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
663
+ }) : function(o, v) {
664
+ o["default"] = v;
665
+ });
666
+ var __importStar = (this && this.__importStar) || (function () {
667
+ var ownKeys = function(o) {
668
+ ownKeys = Object.getOwnPropertyNames || function (o) {
669
+ var ar = [];
670
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
671
+ return ar;
672
+ };
673
+ return ownKeys(o);
674
+ };
675
+ return function (mod) {
676
+ if (mod && mod.__esModule) return mod;
677
+ var result = {};
678
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
679
+ __setModuleDefault(result, mod);
680
+ return result;
681
+ };
682
+ })();
683
+ Object.defineProperty(exports, "__esModule", { value: true });
684
+ exports.makeLibSignalRepository = makeLibSignalRepository;
685
+ // @ts-ignore
686
+ const libsignal = __importStar(require("libsignal"));
687
+ // @ts-ignore
688
+ const protobufs_js_1 = require("libsignal/src/protobufs.js");
689
+ const index_js_1 = require("../Addon/index.js");
690
+ const index_js_2 = require("../Utils/index.js");
691
+ const index_js_3 = require("../WABinary/index.js");
692
+ const sender_key_name_js_1 = require("./Group/sender-key-name.js");
693
+ const sender_key_record_js_1 = require("./Group/sender-key-record.js");
694
+ const index_js_4 = require("./Group/index.js");
695
+ const lid_mapping_js_1 = require("./lid-mapping.js");
696
+ /** Extract identity key from PreKeyWhisperMessage for identity change detection */
697
+ function extractIdentityFromPkmsg(ciphertext) {
698
+ try {
699
+ if (!ciphertext || ciphertext.length < 2) {
700
+ return undefined;
701
+ }
702
+ // Version byte check (version 3)
703
+ const version = ciphertext[0];
704
+ if ((version & 0xf) !== 3) {
705
+ return undefined;
706
+ }
707
+ // Parse protobuf (skip version byte)
708
+ const preKeyProto = protobufs_js_1.PreKeyWhisperMessage.decode(ciphertext.slice(1));
709
+ if (preKeyProto.identityKey?.length === 33) {
710
+ return new Uint8Array(preKeyProto.identityKey);
711
+ }
712
+ return undefined;
713
+ }
714
+ catch {
715
+ return undefined;
716
+ }
717
+ }
718
+ function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
719
+ const lidMapping = new lid_mapping_js_1.LIDMappingStore(auth.keys, logger, pnToLIDFunc);
720
+ const storage = signalStorage(auth, lidMapping);
721
+ const parsedKeys = auth.keys;
722
+ const migratedSessionCache = (0, index_js_1.createCache)({
723
+ ttl: 3 * 24 * 60 * 60 // 3 days
724
+ });
725
+ const ensureSenderKeyAndCreateSkdm = async (group, meId) => {
726
+ const senderName = jidToSignalSenderKeyName(group, meId);
727
+ const senderNameStr = senderName.toString();
728
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
729
+ if (!senderKey) {
730
+ await storage.storeSenderKey(senderName, new sender_key_record_js_1.SenderKeyRecord());
731
+ }
732
+ const skdm = await new index_js_4.GroupSessionBuilder(storage).create(senderName);
733
+ return { senderName, skdm };
734
+ };
735
+ const repository = {
736
+ decryptGroupMessage({ group, authorJid, msg }) {
737
+ const senderName = jidToSignalSenderKeyName(group, authorJid);
738
+ const cipher = new index_js_4.GroupCipher(storage, senderName);
739
+ // Use transaction to ensure atomicity
740
+ return parsedKeys.transaction(async () => {
741
+ return cipher.decrypt(msg);
742
+ }, group);
743
+ },
744
+ async processSenderKeyDistributionMessage({ item, authorJid }) {
745
+ const builder = new index_js_4.GroupSessionBuilder(storage);
746
+ if (!item.groupId) {
747
+ throw new Error('Group ID is required for sender key distribution message');
748
+ }
749
+ const senderName = jidToSignalSenderKeyName(item.groupId, authorJid);
750
+ const senderMsg = new index_js_4.SenderKeyDistributionMessage(null, null, null, null, item.axolotlSenderKeyDistributionMessage);
751
+ const senderNameStr = senderName.toString();
752
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
753
+ if (!senderKey) {
754
+ await storage.storeSenderKey(senderName, new sender_key_record_js_1.SenderKeyRecord());
755
+ }
756
+ return parsedKeys.transaction(async () => {
757
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
758
+ if (!senderKey) {
759
+ await storage.storeSenderKey(senderName, new sender_key_record_js_1.SenderKeyRecord());
760
+ }
761
+ await builder.process(senderName, senderMsg);
762
+ }, item.groupId);
763
+ },
764
+ async decryptMessage({ jid, type, ciphertext }) {
765
+ const addr = jidToSignalProtocolAddress(jid);
766
+ const session = new libsignal.SessionCipher(storage, addr);
767
+ // Extract and save sender's identity key before decryption for identity change detection
768
+ if (type === 'pkmsg') {
769
+ const identityKey = extractIdentityFromPkmsg(ciphertext);
770
+ if (identityKey) {
771
+ const addrStr = addr.toString();
772
+ const identityChanged = await storage.saveIdentity(addrStr, identityKey);
773
+ if (identityChanged) {
774
+ logger.info({ jid, addr: addrStr }, 'identity key changed or new contact, session will be re-established');
775
+ }
776
+ }
777
+ }
778
+ async function doDecrypt() {
779
+ let result;
780
+ switch (type) {
781
+ case 'pkmsg':
782
+ result = await session.decryptPreKeyWhisperMessage(ciphertext);
783
+ break;
784
+ case 'msg':
785
+ result = await session.decryptWhisperMessage(ciphertext);
786
+ break;
787
+ }
788
+ return result;
789
+ }
790
+ // If it's not a sync message, we need to ensure atomicity
791
+ // For regular messages, we use a transaction to ensure atomicity
792
+ return parsedKeys.transaction(async () => {
793
+ return await doDecrypt();
794
+ }, jid);
795
+ },
796
+ async encryptMessage({ jid, data }) {
797
+ const addr = jidToSignalProtocolAddress(jid);
798
+ const cipher = new libsignal.SessionCipher(storage, addr);
799
+ // Use transaction to ensure atomicity
800
+ return parsedKeys.transaction(async () => {
801
+ const { type: sigType, body } = await cipher.encrypt(data);
802
+ const type = sigType === 3 ? 'pkmsg' : 'msg';
803
+ return { type, ciphertext: Buffer.from(body, 'binary') };
804
+ }, jid);
805
+ },
806
+ async encryptGroupMessage({ group, meId, data }) {
807
+ return parsedKeys.transaction(async () => {
808
+ const { senderName, skdm } = await ensureSenderKeyAndCreateSkdm(group, meId);
809
+ const ciphertext = await new index_js_4.GroupCipher(storage, senderName).encrypt(data);
810
+ return { ciphertext, senderKeyDistributionMessage: skdm.serialize() };
811
+ }, group);
812
+ },
813
+ async getSenderKeyDistributionMessage({ group, meId }) {
814
+ return parsedKeys.transaction(async () => {
815
+ const { skdm } = await ensureSenderKeyAndCreateSkdm(group, meId);
816
+ return skdm.serialize();
817
+ }, group);
818
+ },
819
+ async hasSenderKey({ group, meId }) {
820
+ const senderName = jidToSignalSenderKeyName(group, meId).toString();
821
+ const { [senderName]: key } = await auth.keys.get('sender-key', [senderName]);
822
+ return !!key;
823
+ },
824
+ async getSessionInfo(jid) {
825
+ const addr = jidToSignalProtocolAddress(jid).toString();
826
+ const session = (await storage.loadSession(addr));
827
+ if (!session) {
828
+ return null;
829
+ }
830
+ const open = session.getOpenSession?.();
831
+ const baseKey = open?.indexInfo?.baseKey;
832
+ const registrationId = open?.registrationId;
833
+ if (!baseKey || typeof registrationId !== 'number') {
834
+ return null;
835
+ }
836
+ return { baseKey: new Uint8Array(baseKey), registrationId };
837
+ },
838
+ async injectE2ESession({ jid, session }) {
839
+ logger.trace({ jid }, 'injecting E2EE session');
840
+ const cipher = new libsignal.SessionBuilder(storage, jidToSignalProtocolAddress(jid));
841
+ return parsedKeys.transaction(async () => {
842
+ // libsignal runtime accepts an absent prekey (initOutgoing checks `device.preKey && ...`)
843
+ // but the bundled .d.ts marks it required.
844
+ await cipher.initOutgoing(session);
845
+ }, jid);
846
+ },
847
+ jidToSignalProtocolAddress(jid) {
848
+ return jidToSignalProtocolAddress(jid).toString();
849
+ },
850
+ // Optimized direct access to LID mapping store
851
+ lidMapping,
852
+ async validateSession(jid) {
853
+ try {
854
+ const addr = jidToSignalProtocolAddress(jid);
855
+ const session = await storage.loadSession(addr.toString());
856
+ if (!session) {
857
+ return { exists: false, reason: 'no session' };
858
+ }
859
+ if (!session.haveOpenSession()) {
860
+ return { exists: false, reason: 'no open session' };
861
+ }
862
+ return { exists: true };
863
+ }
864
+ catch (error) {
865
+ return { exists: false, reason: 'validation error' };
866
+ }
867
+ },
868
+ async deleteSession(jids) {
869
+ if (!jids.length)
870
+ return;
871
+ // Convert JIDs to signal addresses and prepare for bulk deletion
872
+ const sessionUpdates = {};
873
+ jids.forEach(jid => {
874
+ const addr = jidToSignalProtocolAddress(jid);
875
+ sessionUpdates[addr.toString()] = null;
876
+ });
877
+ // Single transaction for all deletions
878
+ return parsedKeys.transaction(async () => {
879
+ await auth.keys.set({ session: sessionUpdates });
880
+ }, `delete-${jids.length}-sessions`);
881
+ },
882
+ close() {
883
+ migratedSessionCache.flushAll();
884
+ lidMapping.close();
885
+ },
886
+ async migrateSession(fromJid, toJid) {
887
+ // TODO: use usync to handle this entire mess
888
+ if (!fromJid || (!(0, index_js_3.isLidUser)(toJid) && !(0, index_js_3.isHostedLidUser)(toJid)))
889
+ return { migrated: 0, skipped: 0, total: 0 };
890
+ // Only support PN to LID migration
891
+ if (!(0, index_js_3.isPnUser)(fromJid) && !(0, index_js_3.isHostedPnUser)(fromJid)) {
892
+ return { migrated: 0, skipped: 0, total: 1 };
893
+ }
894
+ const { user } = (0, index_js_3.jidDecode)(fromJid);
895
+ logger.debug({ fromJid }, 'bulk device migration - loading all user devices');
896
+ // Get user's device list from storage
897
+ const { [user]: userDevices } = await parsedKeys.get('device-list', [user]);
898
+ if (!userDevices) {
899
+ return { migrated: 0, skipped: 0, total: 0 };
900
+ }
901
+ const { device: fromDevice } = (0, index_js_3.jidDecode)(fromJid);
902
+ const fromDeviceStr = fromDevice?.toString() || '0';
903
+ if (!userDevices.includes(fromDeviceStr)) {
904
+ userDevices.push(fromDeviceStr);
905
+ }
906
+ // Filter out cached devices before database fetch
907
+ const uncachedDevices = userDevices.filter(device => {
908
+ const deviceKey = `${user}.${device}`;
909
+ return !migratedSessionCache.has(deviceKey);
910
+ });
911
+ // Bulk check session existence only for uncached devices
912
+ const deviceSessionKeys = uncachedDevices.map(device => `${user}.${device}`);
913
+ const existingSessions = await parsedKeys.get('session', deviceSessionKeys);
914
+ // Step 3: Convert existing sessions to JIDs (only migrate sessions that exist)
915
+ const deviceJids = [];
916
+ for (const [sessionKey, sessionData] of Object.entries(existingSessions)) {
917
+ if (sessionData) {
918
+ // Session exists in storage
919
+ const deviceStr = sessionKey.split('.')[1];
920
+ if (!deviceStr)
921
+ continue;
922
+ const deviceNum = parseInt(deviceStr);
923
+ let jid = deviceNum === 0 ? `${user}@s.whatsapp.net` : `${user}:${deviceNum}@s.whatsapp.net`;
924
+ if (deviceNum === 99) {
925
+ jid = `${user}:99@hosted`;
926
+ }
927
+ deviceJids.push(jid);
928
+ }
929
+ }
930
+ logger.debug({
931
+ fromJid,
932
+ totalDevices: userDevices.length,
933
+ devicesWithSessions: deviceJids.length,
934
+ devices: deviceJids
935
+ }, 'bulk device migration complete - all user devices processed');
936
+ // Single transaction for all migrations
937
+ return parsedKeys.transaction(async () => {
938
+ const migrationOps = deviceJids.map(jid => {
939
+ const lidWithDevice = (0, index_js_3.transferDevice)(jid, toJid);
940
+ const fromDecoded = (0, index_js_3.jidDecode)(jid);
941
+ const toDecoded = (0, index_js_3.jidDecode)(lidWithDevice);
942
+ return {
943
+ fromJid: jid,
944
+ toJid: lidWithDevice,
945
+ pnUser: fromDecoded.user,
946
+ lidUser: toDecoded.user,
947
+ deviceId: fromDecoded.device || 0,
948
+ fromAddr: jidToSignalProtocolAddress(jid),
949
+ toAddr: jidToSignalProtocolAddress(lidWithDevice)
950
+ };
951
+ });
952
+ const totalOps = migrationOps.length;
953
+ let migratedCount = 0;
954
+ // Bulk fetch PN sessions - already exist (verified during device discovery)
955
+ const pnAddrStrings = Array.from(new Set(migrationOps.map(op => op.fromAddr.toString())));
956
+ const pnSessions = await parsedKeys.get('session', pnAddrStrings);
957
+ // Prepare bulk session updates (PN → LID migration + deletion)
958
+ const sessionUpdates = {};
959
+ for (const op of migrationOps) {
960
+ const pnAddrStr = op.fromAddr.toString();
961
+ const lidAddrStr = op.toAddr.toString();
962
+ const pnSession = pnSessions[pnAddrStr];
963
+ if (pnSession) {
964
+ // Session exists (guaranteed from device discovery)
965
+ const fromSession = libsignal.SessionRecord.deserialize(pnSession);
966
+ if (fromSession.haveOpenSession()) {
967
+ // Queue for bulk update: copy to LID, delete from PN
968
+ sessionUpdates[lidAddrStr] = fromSession.serialize();
969
+ sessionUpdates[pnAddrStr] = null;
970
+ migratedCount++;
971
+ }
972
+ }
973
+ }
974
+ // Single bulk session update for all migrations
975
+ if (Object.keys(sessionUpdates).length > 0) {
976
+ await parsedKeys.set({ session: sessionUpdates });
977
+ logger.debug({ migratedSessions: migratedCount }, 'bulk session migration complete');
978
+ // Cache device-level migrations
979
+ for (const op of migrationOps) {
980
+ if (sessionUpdates[op.toAddr.toString()]) {
981
+ const deviceKey = `${op.pnUser}.${op.deviceId}`;
982
+ migratedSessionCache.set(deviceKey, true);
983
+ }
984
+ }
985
+ }
986
+ const skippedCount = totalOps - migratedCount;
987
+ return { migrated: migratedCount, skipped: skippedCount, total: totalOps };
988
+ }, `migrate-${deviceJids.length}-sessions-${(0, index_js_3.jidDecode)(toJid)?.user}`);
989
+ }
990
+ };
991
+ return repository;
992
+ }
993
+ const jidToSignalProtocolAddress = (jid) => {
994
+ const decoded = (0, index_js_3.jidDecode)(jid);
995
+ const { user, device, server, domainType } = decoded;
996
+ if (!user) {
997
+ throw new Error(`JID decoded but user is empty: "${jid}" -> user: "${user}", server: "${server}", device: ${device}`);
998
+ }
999
+ const signalUser = domainType !== index_js_3.WAJIDDomains.WHATSAPP ? `${user}_${domainType}` : user;
1000
+ const finalDevice = device || 0;
1001
+ if (device === 99 && decoded.server !== 'hosted' && decoded.server !== 'hosted.lid') {
1002
+ throw new Error('Unexpected non-hosted device JID with device 99. This ID seems invalid. ID:' + jid);
1003
+ }
1004
+ return new libsignal.ProtocolAddress(signalUser, finalDevice);
1005
+ };
1006
+ const jidToSignalSenderKeyName = (group, user) => {
1007
+ return new sender_key_name_js_1.SenderKeyName(group, jidToSignalProtocolAddress(user));
1008
+ };
1009
+ function signalStorage({ creds, keys }, lidMapping) {
1010
+ // Shared function to resolve PN signal address to LID if mapping exists
1011
+ const resolveLIDSignalAddress = async (id) => {
1012
+ if (id.includes('.')) {
1013
+ const [deviceId, device] = id.split('.');
1014
+ const [user, domainType_] = deviceId.split('_');
1015
+ const domainType = parseInt(domainType_ || '0');
1016
+ if (domainType === index_js_3.WAJIDDomains.LID || domainType === index_js_3.WAJIDDomains.HOSTED_LID)
1017
+ return id;
1018
+ const pnJid = `${user}${device !== '0' ? `:${device}` : ''}@${domainType === index_js_3.WAJIDDomains.HOSTED ? 'hosted' : 's.whatsapp.net'}`;
1019
+ const lidForPN = await lidMapping.getLIDForPN(pnJid);
1020
+ if (lidForPN) {
1021
+ const lidAddr = jidToSignalProtocolAddress(lidForPN);
1022
+ return lidAddr.toString();
1023
+ }
1024
+ }
1025
+ return id;
1026
+ };
1027
+ return {
1028
+ loadSession: async (id) => {
1029
+ try {
1030
+ const wireJid = await resolveLIDSignalAddress(id);
1031
+ const { [wireJid]: sess } = await keys.get('session', [wireJid]);
1032
+ if (sess) {
1033
+ return libsignal.SessionRecord.deserialize(sess);
1034
+ }
1035
+ }
1036
+ catch (e) {
1037
+ return null;
1038
+ }
1039
+ return null;
1040
+ },
1041
+ storeSession: async (id, session) => {
1042
+ const wireJid = await resolveLIDSignalAddress(id);
1043
+ await keys.set({ session: { [wireJid]: session.serialize() } });
1044
+ },
1045
+ isTrustedIdentity: () => {
1046
+ return true; // TOFU - Trust on First Use (same as WhatsApp Web)
1047
+ },
1048
+ loadIdentityKey: async (id) => {
1049
+ const wireJid = await resolveLIDSignalAddress(id);
1050
+ const { [wireJid]: key } = await keys.get('identity-key', [wireJid]);
1051
+ return key || undefined;
1052
+ },
1053
+ saveIdentity: async (id, identityKey) => {
1054
+ const wireJid = await resolveLIDSignalAddress(id);
1055
+ const { [wireJid]: existingKey } = await keys.get('identity-key', [wireJid]);
1056
+ const keysMatch = existingKey?.length === identityKey.length && existingKey.every((byte, i) => byte === identityKey[i]);
1057
+ if (existingKey && !keysMatch) {
1058
+ // Identity changed - clear session and update key
1059
+ await keys.set({
1060
+ session: { [wireJid]: null },
1061
+ 'identity-key': { [wireJid]: identityKey }
1062
+ });
1063
+ return true;
1064
+ }
1065
+ if (!existingKey) {
1066
+ // New contact - Trust on First Use (TOFU)
1067
+ await keys.set({ 'identity-key': { [wireJid]: identityKey } });
1068
+ return true;
1069
+ }
1070
+ return false;
1071
+ },
1072
+ loadPreKey: async (id) => {
1073
+ const keyId = id.toString();
1074
+ const { [keyId]: key } = await keys.get('pre-key', [keyId]);
1075
+ if (key) {
1076
+ return {
1077
+ privKey: Buffer.from(key.private),
1078
+ pubKey: Buffer.from(key.public)
1079
+ };
1080
+ }
1081
+ },
1082
+ removePreKey: (id) => keys.set({ 'pre-key': { [id]: null } }),
1083
+ loadSignedPreKey: () => {
1084
+ const key = creds.signedPreKey;
1085
+ return {
1086
+ privKey: Buffer.from(key.keyPair.private),
1087
+ pubKey: Buffer.from(key.keyPair.public)
1088
+ };
1089
+ },
1090
+ loadSenderKey: async (senderKeyName) => {
1091
+ const keyId = senderKeyName.toString();
1092
+ const { [keyId]: key } = await keys.get('sender-key', [keyId]);
1093
+ if (key) {
1094
+ return sender_key_record_js_1.SenderKeyRecord.deserialize(key);
1095
+ }
1096
+ return new sender_key_record_js_1.SenderKeyRecord();
1097
+ },
1098
+ storeSenderKey: async (senderKeyName, key) => {
1099
+ const keyId = senderKeyName.toString();
1100
+ const serialized = JSON.stringify(key.serialize());
1101
+ await keys.set({ 'sender-key': { [keyId]: Buffer.from(serialized, 'utf-8') } });
1102
+ },
1103
+ getOurRegistrationId: () => creds.registrationId,
1104
+ getOurIdentity: () => {
1105
+ const { signedIdentityKey } = creds;
1106
+ return {
1107
+ privKey: Buffer.from(signedIdentityKey.private),
1108
+ pubKey: Buffer.from((0, index_js_2.generateSignalPubKey)(signedIdentityKey.public))
1109
+ };
1110
+ }
1111
+ };
1112
+ }
1113
+
1114
+ return module.exports;
1115
+ })();
1116
+ for (const key of Object.keys(__kageModule125)) {
1117
+ if (key !== '__esModule' && !Object.prototype.hasOwnProperty.call(exports,key)) Object.defineProperty(exports,key,{enumerable:true,configurable:true,get:()=>__kageModule125[key]});
1118
+ }
1119
+ Object.defineProperty(exports, Symbol.for('kage.advanced'), {value:__kageModule125, configurable:true});