@hansaka02/baileys 7.3.2 → 7.3.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 (210) hide show
  1. package/lib/Defaults/baileys-version.json +2 -2
  2. package/lib/Defaults/connection.js +51 -0
  3. package/lib/Defaults/constants.js +74 -0
  4. package/lib/Defaults/history.js +19 -0
  5. package/lib/Defaults/index.js +36 -142
  6. package/lib/Defaults/media.js +48 -0
  7. package/lib/Defaults/prefix.js +18 -0
  8. package/lib/Signal/Group/group-session-builder.js +10 -42
  9. package/lib/Signal/Group/group_cipher.js +9 -6
  10. package/lib/Signal/Group/index.js +39 -53
  11. package/lib/Signal/Group/keyhelper.js +8 -41
  12. package/lib/Signal/Group/sender-chain-key.js +5 -18
  13. package/lib/Signal/Group/sender-key-distribution-message.js +7 -7
  14. package/lib/Signal/Group/sender-key-message.js +12 -8
  15. package/lib/Signal/Group/sender-key-record.js +7 -16
  16. package/lib/Signal/Group/sender-key-state.js +15 -61
  17. package/lib/Signal/Group/sender-message-key.js +2 -2
  18. package/lib/Signal/libsignal.js +237 -177
  19. package/lib/Signal/lid-mapping.js +128 -71
  20. package/lib/Socket/Client/types.js +2 -2
  21. package/lib/Socket/Client/websocket.js +25 -16
  22. package/lib/Socket/business.js +46 -33
  23. package/lib/Socket/chats.js +286 -170
  24. package/lib/Socket/community.js +215 -77
  25. package/lib/Socket/groups.js +77 -61
  26. package/lib/Socket/index.js +4 -4
  27. package/lib/Socket/messages-recv.js +629 -457
  28. package/lib/Socket/messages-send.js +645 -656
  29. package/lib/Socket/mex.js +61 -0
  30. package/lib/Socket/newsletter.js +166 -245
  31. package/lib/Socket/socket.js +396 -170
  32. package/lib/Store/index.js +27 -11
  33. package/lib/Store/make-cache-manager-store.js +14 -15
  34. package/lib/Store/make-in-memory-store.js +28 -24
  35. package/lib/Types/LabelAssociation.js +2 -2
  36. package/lib/Types/Message.js +6 -6
  37. package/lib/Types/MexUpdates.js +5 -5
  38. package/lib/Types/Newsletter.js +32 -25
  39. package/lib/Types/State.js +4 -4
  40. package/lib/Types/index.js +28 -12
  41. package/lib/Utils/auth-utils.js +212 -375
  42. package/lib/Utils/baileys-event-stream.js +68 -69
  43. package/lib/Utils/browser-utils.js +43 -0
  44. package/lib/Utils/business.js +63 -53
  45. package/lib/Utils/chat-utils.js +241 -106
  46. package/lib/Utils/crypto.js +25 -45
  47. package/lib/Utils/decode-wa-message.js +361 -311
  48. package/lib/Utils/event-buffer.js +97 -42
  49. package/lib/Utils/generics.js +90 -207
  50. package/lib/Utils/history.js +29 -27
  51. package/lib/Utils/index.js +28 -14
  52. package/lib/Utils/link-preview.js +24 -62
  53. package/lib/Utils/logger.js +5 -5
  54. package/lib/Utils/lt-hash.js +29 -23
  55. package/lib/Utils/make-mutex.js +26 -28
  56. package/lib/Utils/message-retry-manager.js +55 -7
  57. package/lib/Utils/messages-media.js +434 -247
  58. package/lib/Utils/messages.js +963 -917
  59. package/lib/Utils/noise-handler.js +60 -20
  60. package/lib/Utils/pre-key-manager.js +126 -0
  61. package/lib/Utils/process-message.js +216 -141
  62. package/lib/Utils/signal.js +75 -37
  63. package/lib/Utils/use-multi-file-auth-state.js +18 -22
  64. package/lib/Utils/validate-connection.js +96 -66
  65. package/lib/WABinary/constants.js +1268 -1268
  66. package/lib/WABinary/decode.js +62 -34
  67. package/lib/WABinary/encode.js +57 -36
  68. package/lib/WABinary/generic-utils.js +4 -4
  69. package/lib/WABinary/index.js +27 -11
  70. package/lib/WABinary/jid-utils.js +58 -11
  71. package/lib/WAM/constants.js +19064 -11563
  72. package/lib/WAM/encode.js +71 -14
  73. package/lib/WAM/index.js +27 -11
  74. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +20 -16
  75. package/lib/WAUSync/Protocols/USyncContactProtocol.js +2 -2
  76. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +7 -4
  77. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +2 -2
  78. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +0 -2
  79. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +2 -2
  80. package/lib/WAUSync/Protocols/index.js +27 -11
  81. package/lib/WAUSync/USyncQuery.js +51 -28
  82. package/lib/WAUSync/index.js +27 -11
  83. package/lib/index.js +60 -31
  84. package/package.json +12 -17
  85. package/WAProto/AICommon/AICommon.d.ts +0 -11702
  86. package/WAProto/Adv/Adv.d.ts +0 -643
  87. package/WAProto/BotMetadata/BotMetadata.d.ts +0 -5654
  88. package/WAProto/Cert/Cert.d.ts +0 -613
  89. package/WAProto/ChatLockSettings/ChatLockSettings.d.ts +0 -476
  90. package/WAProto/CompanionReg/CompanionReg.d.ts +0 -1361
  91. package/WAProto/DeviceCapabilities/DeviceCapabilities.d.ts +0 -577
  92. package/WAProto/E2E/E2E.d.ts +0 -41724
  93. package/WAProto/Ephemeral/Ephemeral.d.ts +0 -114
  94. package/WAProto/HistorySync/HistorySync.d.ts +0 -51700
  95. package/WAProto/LidMigrationSyncPayload/LidMigrationSyncPayload.d.ts +0 -229
  96. package/WAProto/MdStorageChatRowOpaqueData/MdStorageChatRowOpaqueData.d.ts +0 -583
  97. package/WAProto/MdStorageMsgRowOpaqueData/MdStorageMsgRowOpaqueData.d.ts +0 -42897
  98. package/WAProto/MmsRetry/MmsRetry.d.ts +0 -243
  99. package/WAProto/Protocol/Protocol.d.ts +0 -270
  100. package/WAProto/Reporting/Reporting.d.ts +0 -371
  101. package/WAProto/ServerSync/ServerSync.d.ts +0 -1285
  102. package/WAProto/SignalLocalStorageProtocol/SignalLocalStorageProtocol.d.ts +0 -1868
  103. package/WAProto/SignalWhisperTextProtocol/SignalWhisperTextProtocol.d.ts +0 -767
  104. package/WAProto/StatusAttributions/StatusAttributions.d.ts +0 -1027
  105. package/WAProto/SyncAction/SyncAction.d.ts +0 -11193
  106. package/WAProto/UserPassword/UserPassword.d.ts +0 -363
  107. package/WAProto/VnameCert/VnameCert.d.ts +0 -821
  108. package/WAProto/Wa6/Wa6.d.ts +0 -2128
  109. package/WAProto/Web/Web.d.ts +0 -46383
  110. package/WAProto/index.d.ts +0 -55
  111. package/lib/Defaults/index.d.ts +0 -77
  112. package/lib/Signal/Group/ciphertext-message.d.ts +0 -9
  113. package/lib/Signal/Group/group-session-builder.d.ts +0 -17
  114. package/lib/Signal/Group/group_cipher.d.ts +0 -19
  115. package/lib/Signal/Group/index.d.ts +0 -11
  116. package/lib/Signal/Group/keyhelper.d.ts +0 -16
  117. package/lib/Signal/Group/sender-chain-key.d.ts +0 -14
  118. package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -17
  119. package/lib/Signal/Group/sender-key-message.d.ts +0 -19
  120. package/lib/Signal/Group/sender-key-name.d.ts +0 -19
  121. package/lib/Signal/Group/sender-key-record.d.ts +0 -32
  122. package/lib/Signal/Group/sender-key-state.d.ts +0 -44
  123. package/lib/Signal/Group/sender-message-key.d.ts +0 -11
  124. package/lib/Signal/libsignal.d.ts +0 -8
  125. package/lib/Signal/lid-mapping.d.ts +0 -28
  126. package/lib/Socket/Client/index.d.ts +0 -2
  127. package/lib/Socket/Client/types.d.ts +0 -16
  128. package/lib/Socket/Client/websocket.d.ts +0 -13
  129. package/lib/Socket/business.d.ts +0 -187
  130. package/lib/Socket/chats.d.ts +0 -97
  131. package/lib/Socket/community.d.ts +0 -129
  132. package/lib/Socket/groups.d.ts +0 -129
  133. package/lib/Socket/index.d.ts +0 -191
  134. package/lib/Socket/messages-recv.d.ts +0 -174
  135. package/lib/Socket/messages-send.d.ts +0 -165
  136. package/lib/Socket/newsletter.d.ts +0 -145
  137. package/lib/Socket/socket.d.ts +0 -45
  138. package/lib/Socket/usync.d.ts +0 -37
  139. package/lib/Socket/usync.js +0 -83
  140. package/lib/Store/index.d.ts +0 -4
  141. package/lib/Store/make-cache-manager-store.d.ts +0 -14
  142. package/lib/Store/make-in-memory-store.d.ts +0 -123
  143. package/lib/Store/make-ordered-dictionary.d.ts +0 -12
  144. package/lib/Store/object-repository.d.ts +0 -10
  145. package/lib/Types/Auth.d.ts +0 -121
  146. package/lib/Types/Bussiness.d.ts +0 -28
  147. package/lib/Types/Call.d.ts +0 -14
  148. package/lib/Types/Chat.d.ts +0 -143
  149. package/lib/Types/Contact.d.ts +0 -23
  150. package/lib/Types/Events.d.ts +0 -226
  151. package/lib/Types/GroupMetadata.d.ts +0 -66
  152. package/lib/Types/Label.d.ts +0 -48
  153. package/lib/Types/LabelAssociation.d.ts +0 -35
  154. package/lib/Types/Message.d.ts +0 -484
  155. package/lib/Types/MexUpdates.d.ts +0 -9
  156. package/lib/Types/Newsletter.d.ts +0 -109
  157. package/lib/Types/Product.d.ts +0 -92
  158. package/lib/Types/Signal.d.ts +0 -98
  159. package/lib/Types/Socket.d.ts +0 -141
  160. package/lib/Types/State.d.ts +0 -41
  161. package/lib/Types/USync.d.ts +0 -26
  162. package/lib/Types/index.d.ts +0 -80
  163. package/lib/Utils/auth-utils.d.ts +0 -21
  164. package/lib/Utils/baileys-event-stream.d.ts +0 -18
  165. package/lib/Utils/business.d.ts +0 -29
  166. package/lib/Utils/chat-utils.d.ts +0 -82
  167. package/lib/Utils/crypto.d.ts +0 -56
  168. package/lib/Utils/decode-wa-message.d.ts +0 -53
  169. package/lib/Utils/event-buffer.d.ts +0 -39
  170. package/lib/Utils/generics.d.ts +0 -117
  171. package/lib/Utils/history.d.ts +0 -23
  172. package/lib/Utils/index.d.ts +0 -20
  173. package/lib/Utils/link-preview.d.ts +0 -23
  174. package/lib/Utils/logger.d.ts +0 -13
  175. package/lib/Utils/lt-hash.d.ts +0 -14
  176. package/lib/Utils/make-mutex.d.ts +0 -9
  177. package/lib/Utils/message-retry-manager.d.ts +0 -88
  178. package/lib/Utils/messages-media.d.ts +0 -135
  179. package/lib/Utils/messages.d.ts +0 -105
  180. package/lib/Utils/noise-handler.d.ts +0 -20
  181. package/lib/Utils/process-message.d.ts +0 -49
  182. package/lib/Utils/signal.d.ts +0 -42
  183. package/lib/Utils/use-mongo-file-auth-state.d.ts +0 -6
  184. package/lib/Utils/use-mongo-file-auth-state.js +0 -84
  185. package/lib/Utils/use-multi-file-auth-state.d.ts +0 -13
  186. package/lib/Utils/use-single-file-auth-state.d.ts +0 -13
  187. package/lib/Utils/use-single-file-auth-state.js +0 -80
  188. package/lib/Utils/validate-connection.d.ts +0 -13
  189. package/lib/WABinary/constants.d.ts +0 -30
  190. package/lib/WABinary/decode.d.ts +0 -9
  191. package/lib/WABinary/encode.d.ts +0 -3
  192. package/lib/WABinary/generic-utils.d.ts +0 -28
  193. package/lib/WABinary/index.d.ts +0 -5
  194. package/lib/WABinary/jid-utils.d.ts +0 -58
  195. package/lib/WABinary/types.d.ts +0 -22
  196. package/lib/WAM/BinaryInfo.d.ts +0 -16
  197. package/lib/WAM/constants.d.ts +0 -47
  198. package/lib/WAM/encode.d.ts +0 -3
  199. package/lib/WAM/index.d.ts +0 -3
  200. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts +0 -28
  201. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -10
  202. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -26
  203. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -14
  204. package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts +0 -10
  205. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -14
  206. package/lib/WAUSync/Protocols/index.d.ts +0 -6
  207. package/lib/WAUSync/USyncQuery.d.ts +0 -31
  208. package/lib/WAUSync/USyncUser.d.ts +0 -12
  209. package/lib/WAUSync/index.d.ts +0 -3
  210. package/lib/index.d.ts +0 -13
@@ -1,99 +1,88 @@
1
1
  "use strict"
2
2
 
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k
5
- var desc = Object.getOwnPropertyDescriptor(m, k)
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k] } }
8
- }
9
- Object.defineProperty(o, k2, desc)
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k
12
- o[k2] = m[k]
13
- }))
14
-
15
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
- Object.defineProperty(o, "default", { enumerable: true, value: v })
17
- }) : function(o, v) {
18
- o["default"] = v
19
- })
20
-
21
- var __importStar = (this && this.__importStar) || (function () {
22
- var ownKeys = function(o) {
23
- ownKeys = Object.getOwnPropertyNames || function (o) {
24
- var ar = []
25
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k
26
- return ar
27
- }
28
- return ownKeys(o)
29
- }
30
- return function (mod) {
31
- if (mod && mod.__esModule) return mod
32
- var result = {}
33
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i])
34
- __setModuleDefault(result, mod)
35
- return result
36
- }
37
- })()
38
-
39
3
  Object.defineProperty(exports, "__esModule", { value: true })
40
4
 
41
- const libsignal = __importStar(require("@itsukichan/libsignal-node"))
42
- const Utils_1 = require("../Utils")
43
- const WABinary_1 = require("../WABinary")
44
- const sender_key_name_1 = require("./Group/sender-key-name")
45
- const sender_key_record_1 = require("./Group/sender-key-record")
46
- const Group_1 = require("./Group")
47
- const LIDMappingStore_1 = require("./lid-mapping")
5
+ const {
6
+ SessionCipher,
7
+ SessionBuilder,
8
+ SessionRecord,
9
+ ProtocolAddress
10
+ } = require("@itsukichan/libsignal-node")
11
+ const { generateSignalPubKey } = require("../Utils")
12
+ const {
13
+ isHostedLidUser,
14
+ isHostedPnUser,
15
+ isLidUser,
16
+ isPnUser,
17
+ jidDecode,
18
+ transferDevice,
19
+ WAJIDDomains
20
+ } = require("../WABinary")
21
+ const { SenderKeyName } = require("./Group/sender-key-name")
22
+ const { SenderKeyRecord } = require("./Group/sender-key-record")
23
+ const {
24
+ GroupCipher,
25
+ GroupSessionBuilder,
26
+ SenderKeyDistributionMessage
27
+ } = require("./Group")
28
+ const { LRUCache } = require("lru-cache")
29
+ const { LIDMappingStore } = require("./lid-mapping")
48
30
 
49
- function makeLibSignalRepository(auth, onWhatsAppFunc, logger) {
50
- const lidMapping = new LIDMappingStore_1.LIDMappingStore(auth.keys, onWhatsAppFunc, logger)
31
+ function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
32
+ const lidMapping = new LIDMappingStore(auth.keys, logger, pnToLIDFunc)
51
33
  const storage = signalStorage(auth, lidMapping)
52
34
  const parsedKeys = auth.keys
53
-
54
- function isLikelySyncMessage(addr) {
55
- const key = addr.toString()
56
- // Only bypass for WhatsApp system addresses, not regular user contacts
57
- // Be very specific about sync service patterns
58
- return (key.includes('@lid.whatsapp.net') || // WhatsApp system messages
59
- key.includes('@broadcast') || // Broadcast messages
60
- key.includes('@newsletter'))
61
- }
35
+ const migratedSessionCache = new LRUCache({
36
+ ttl: 3 * 24 * 60 * 60 * 1000, // 7 days
37
+ ttlAutopurge: true,
38
+ updateAgeOnGet: true
39
+ })
62
40
 
63
41
  const repository = {
64
42
  decryptGroupMessage({ group, authorJid, msg }) {
65
43
  const senderName = jidToSignalSenderKeyName(group, authorJid)
66
- const cipher = new Group_1.GroupCipher(storage, senderName)
44
+ const cipher = new GroupCipher(storage, senderName)
45
+
67
46
  // Use transaction to ensure atomicity
68
47
  return parsedKeys.transaction(async () => {
69
48
  return cipher.decrypt(msg)
70
49
  }, group)
71
50
  },
51
+
72
52
  async processSenderKeyDistributionMessage({ item, authorJid }) {
73
- const builder = new Group_1.GroupSessionBuilder(storage)
53
+ const builder = new GroupSessionBuilder(storage)
54
+
74
55
  if (!item.groupId) {
75
56
  throw new Error('Group ID is required for sender key distribution message')
76
57
  }
58
+
77
59
  const senderName = jidToSignalSenderKeyName(item.groupId, authorJid)
78
- const senderMsg = new Group_1.SenderKeyDistributionMessage(null, null, null, null, item.axolotlSenderKeyDistributionMessage)
60
+ const senderMsg = new SenderKeyDistributionMessage(null, null, null, null, item.axolotlSenderKeyDistributionMessage)
79
61
  const senderNameStr = senderName.toString()
80
62
  const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr])
63
+
81
64
  if (!senderKey) {
82
- await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord())
65
+ await storage.storeSenderKey(senderName, new SenderKeyRecord())
83
66
  }
67
+
84
68
  return parsedKeys.transaction(async () => {
85
69
  const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr])
70
+
86
71
  if (!senderKey) {
87
- await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord())
72
+ await storage.storeSenderKey(senderName, new SenderKeyRecord())
88
73
  }
74
+
89
75
  await builder.process(senderName, senderMsg)
90
76
  }, item.groupId)
91
77
  },
78
+
92
79
  async decryptMessage({ jid, type, ciphertext }) {
93
80
  const addr = jidToSignalProtocolAddress(jid)
94
- const session = new libsignal.SessionCipher(storage, addr)
81
+ const session = new SessionCipher(storage, addr)
82
+
95
83
  async function doDecrypt() {
96
84
  let result
85
+
97
86
  switch (type) {
98
87
  case 'pkmsg':
99
88
  result = await session.decryptPreKeyWhisperMessage(ciphertext)
@@ -102,98 +91,91 @@ function makeLibSignalRepository(auth, onWhatsAppFunc, logger) {
102
91
  result = await session.decryptWhisperMessage(ciphertext)
103
92
  break
104
93
  }
94
+
105
95
  return result
106
96
  }
107
- if (isLikelySyncMessage(addr)) {
108
- // If it's a sync message, we can skip the transaction
109
- // as it is likely to be a system message that doesn't require strict atomicity
110
- return await doDecrypt()
111
- }
97
+
112
98
  // If it's not a sync message, we need to ensure atomicity
113
99
  // For regular messages, we use a transaction to ensure atomicity
114
100
  return parsedKeys.transaction(async () => {
115
101
  return await doDecrypt()
116
102
  }, jid)
117
103
  },
104
+
118
105
  async encryptMessage({ jid, data }) {
119
- // LID SINGLE SOURCE OF TRUTH: Always prefer LID when available
120
- let encryptionJid = jid
121
- // Check for LID mapping and use it if session exists
122
- if (jid.includes('@s.whatsapp.net')) {
123
- const lidForPN = await lidMapping.getLIDForPN(jid)
124
- if (lidForPN?.includes('@lid')) {
125
- const lidAddr = jidToSignalProtocolAddress(lidForPN)
126
- const { [lidAddr.toString()]: lidSession } = await auth.keys.get('session', [lidAddr.toString()])
127
- if (lidSession) {
128
- // LID session exists, use it
129
- encryptionJid = lidForPN
130
- }
131
- else {
132
- // Try to migrate if PN session exists
133
- const pnAddr = jidToSignalProtocolAddress(jid)
134
- const { [pnAddr.toString()]: pnSession } = await auth.keys.get('session', [pnAddr.toString()])
135
- if (pnSession) {
136
- // Migrate PN to LID
137
- await repository.migrateSession([jid], lidForPN)
138
- encryptionJid = lidForPN
139
- }
140
- }
141
- }
142
- }
143
- const addr = jidToSignalProtocolAddress(encryptionJid)
144
- const cipher = new libsignal.SessionCipher(storage, addr)
106
+ const addr = jidToSignalProtocolAddress(jid)
107
+ const cipher = new SessionCipher(storage, addr)
108
+
145
109
  // Use transaction to ensure atomicity
146
110
  return parsedKeys.transaction(async () => {
147
111
  const { type: sigType, body } = await cipher.encrypt(data)
148
112
  const type = sigType === 3 ? 'pkmsg' : 'msg'
113
+
149
114
  return { type, ciphertext: Buffer.from(body, 'binary') }
150
115
  }, jid)
151
116
  },
117
+
152
118
  async encryptGroupMessage({ group, meId, data }) {
153
119
  const senderName = jidToSignalSenderKeyName(group, meId)
154
- const builder = new Group_1.GroupSessionBuilder(storage)
120
+ const builder = new GroupSessionBuilder(storage)
155
121
  const senderNameStr = senderName.toString()
122
+
156
123
  return parsedKeys.transaction(async () => {
157
124
  const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr])
125
+
158
126
  if (!senderKey) {
159
- await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord())
127
+ await storage.storeSenderKey(senderName, new SenderKeyRecord())
160
128
  }
129
+
161
130
  const senderKeyDistributionMessage = await builder.create(senderName)
162
- const session = new Group_1.GroupCipher(storage, senderName)
131
+ const session = new GroupCipher(storage, senderName)
163
132
  const ciphertext = await session.encrypt(data)
133
+
164
134
  return {
165
135
  ciphertext,
166
136
  senderKeyDistributionMessage: senderKeyDistributionMessage.serialize()
167
137
  }
168
138
  }, group)
169
- },
139
+ },
140
+
170
141
  async injectE2ESession({ jid, session }) {
171
- const cipher = new libsignal.SessionBuilder(storage, jidToSignalProtocolAddress(jid))
142
+ logger.trace({ jid }, 'injecting E2EE session')
143
+
144
+ const cipher = new SessionBuilder(storage, jidToSignalProtocolAddress(jid))
145
+
172
146
  return parsedKeys.transaction(async () => {
173
147
  await cipher.initOutgoing(session)
174
148
  }, jid)
175
149
  },
150
+
176
151
  jidToSignalProtocolAddress(jid) {
177
152
  return jidToSignalProtocolAddress(jid).toString()
178
153
  },
154
+
179
155
  // Optimized direct access to LID mapping store
180
156
  lidMapping,
157
+
181
158
  async validateSession(jid) {
182
159
  try {
183
160
  const addr = jidToSignalProtocolAddress(jid)
184
161
  const session = await storage.loadSession(addr.toString())
162
+
185
163
  if (!session) {
186
164
  return { exists: false, reason: 'no session' }
187
165
  }
166
+
188
167
  if (!session.haveOpenSession()) {
189
168
  return { exists: false, reason: 'no open session' }
190
169
  }
170
+
191
171
  return { exists: true }
192
172
  }
173
+
193
174
  catch (error) {
194
175
  return { exists: false, reason: 'validation error' }
195
176
  }
196
177
  },
178
+
197
179
  async deleteSession(jids) {
198
180
  if (!jids.length) return
199
181
 
@@ -210,31 +192,81 @@ function makeLibSignalRepository(auth, onWhatsAppFunc, logger) {
210
192
  await auth.keys.set({ session: sessionUpdates })
211
193
  }, `delete-${jids.length}-sessions`)
212
194
  },
213
- async migrateSession(fromJids, toJid) {
214
- if (!fromJids.length || !toJid.includes('@lid'))
195
+
196
+ async migrateSession(fromJid, toJid) {
197
+ // TODO: use usync to handle this entire mess
198
+ if (!fromJid || (!isLidUser(toJid) && !isHostedLidUser(toJid))) {
215
199
  return { migrated: 0, skipped: 0, total: 0 }
216
-
217
- // Filter valid PN JIDs
218
- const validJids = fromJids.filter(jid => jid.includes('@s.whatsapp.net'))
200
+ }
219
201
 
220
- if (!validJids.length)
221
- return { migrated: 0, skipped: 0, total: fromJids.length }
222
-
223
- // Single optimized transaction for all migrations
202
+ // Only support PN to LID migration
203
+ if (!isPnUser(fromJid) && !isHostedPnUser(fromJid)) {
204
+ return { migrated: 0, skipped: 0, total: 1 }
205
+ }
206
+
207
+ const { user } = jidDecode(fromJid)
208
+
209
+ logger.debug({ fromJid }, 'bulk device migration - loading all user devices')
210
+
211
+ // Get user's device list from storage
212
+ const { [user]: userDevices } = await parsedKeys.get('device-list', [user])
213
+
214
+ if (!userDevices) {
215
+ return { migrated: 0, skipped: 0, total: 0 }
216
+ }
217
+
218
+ const { device: fromDevice } = jidDecode(fromJid)
219
+ const fromDeviceStr = fromDevice?.toString() || '0'
220
+
221
+ if (!userDevices.includes(fromDeviceStr)) {
222
+ userDevices.push(fromDeviceStr)
223
+ }
224
+
225
+ // Filter out cached devices before database fetch
226
+ const uncachedDevices = userDevices.filter(device => {
227
+ const deviceKey = `${user}.${device}`
228
+ return !migratedSessionCache.has(deviceKey)
229
+ })
230
+
231
+ // Bulk check session existence only for uncached devices
232
+ const deviceSessionKeys = uncachedDevices.map(device => `${user}.${device}`)
233
+ const existingSessions = await parsedKeys.get('session', deviceSessionKeys)
234
+
235
+ // Step 3: Convert existing sessions to JIDs (only migrate sessions that exist)
236
+ const deviceJids = []
237
+
238
+ for (const [sessionKey, sessionData] of Object.entries(existingSessions)) {
239
+ if (sessionData) {
240
+ // Session exists in storage
241
+ const deviceStr = sessionKey.split('.')[1]
242
+
243
+ if (!deviceStr) continue
244
+
245
+ const deviceNum = parseInt(deviceStr)
246
+
247
+ let jid = deviceNum === 0 ? `${user}@s.whatsapp.net` : `${user}:${deviceNum}@s.whatsapp.net`
248
+
249
+ if (deviceNum === 99) {
250
+ jid = `${user}:99@hosted`
251
+ }
252
+
253
+ deviceJids.push(jid)
254
+ }
255
+ }
256
+
257
+ logger.debug({
258
+ fromJid,
259
+ totalDevices: userDevices.length,
260
+ devicesWithSessions: deviceJids.length,
261
+ devices: deviceJids
262
+ }, 'bulk device migration complete - all user devices processed')
263
+
264
+ // Single transaction for all migrations
224
265
  return parsedKeys.transaction(async () => {
225
- // 1. Batch store all LID mappings
226
- const mappings = validJids.map(jid => ({
227
- lid: WABinary_1.transferDevice(jid, toJid),
228
- pn: jid
229
- }))
230
-
231
- await lidMapping.storeLIDPNMappings(mappings)
232
-
233
- // 2. Prepare migration operations
234
- const migrationOps = validJids.map(jid => {
235
- const lidWithDevice = WABinary_1.transferDevice(jid, toJid)
236
- const fromDecoded = WABinary_1.jidDecode(jid)
237
- const toDecoded = WABinary_1.jidDecode(lidWithDevice)
266
+ const migrationOps = deviceJids.map(jid => {
267
+ const lidWithDevice = transferDevice(jid, toJid)
268
+ const fromDecoded = jidDecode(jid)
269
+ const toDecoded = jidDecode(lidWithDevice)
238
270
 
239
271
  return {
240
272
  fromJid: jid,
@@ -247,106 +279,132 @@ function makeLibSignalRepository(auth, onWhatsAppFunc, logger) {
247
279
  }
248
280
  })
249
281
 
250
- // 3. Batch check which LID sessions already exist
251
- const lidAddrs = migrationOps.map(op => op.toAddr.toString())
252
- const existingSessions = await auth.keys.get('session', lidAddrs)
282
+ const totalOps = migrationOps.length
253
283
 
254
- // 4. Filter out sessions that already have LID sessions
255
- const opsToMigrate = migrationOps.filter(op => !existingSessions[op.toAddr.toString()])
256
- const skippedCount = migrationOps.length - opsToMigrate.length
284
+ let migratedCount = 0
257
285
 
258
- if (!opsToMigrate.length) {
259
- return { migrated: 0, skipped: skippedCount, total: validJids.length };
260
- }
286
+ // Bulk fetch PN sessions - already exist (verified during device discovery)
287
+ const pnAddrStrings = Array.from(new Set(migrationOps.map(op => op.fromAddr.toString())))
288
+ const pnSessions = await parsedKeys.get('session', pnAddrStrings)
289
+
290
+ // Prepare bulk session updates (PN → LID migration + deletion)
291
+ const sessionUpdates = {}
261
292
 
262
- // 5. Execute all migrations in parallel
263
- await Promise.all(opsToMigrate.map(async (op) => {
264
- const fromSession = await storage.loadSession(op.fromAddr.toString())
293
+ for (const op of migrationOps) {
294
+ const pnAddrStr = op.fromAddr.toString()
295
+ const lidAddrStr = op.toAddr.toString()
296
+ const pnSession = pnSessions[pnAddrStr]
265
297
 
266
- if (fromSession?.haveOpenSession()) {
267
- // Copy session to LID address
268
- const sessionBytes = fromSession.serialize()
269
- const copiedSession = libsignal.SessionRecord.deserialize(sessionBytes)
270
- await storage.storeSession(op.toAddr.toString(), copiedSession)
298
+ if (pnSession) {
299
+ // Session exists (guaranteed from device discovery)
300
+ const fromSession = SessionRecord.deserialize(pnSession)
271
301
 
272
- // Delete PN session
273
- await auth.keys.set({ session: { [op.fromAddr.toString()]: null } })
302
+ if (fromSession.haveOpenSession()) {
303
+ // Queue for bulk update: copy to LID, delete from PN
304
+ sessionUpdates[lidAddrStr] = fromSession.serialize()
305
+ sessionUpdates[pnAddrStr] = null
306
+ migratedCount++
307
+ }
274
308
  }
275
- }))
309
+ }
276
310
 
277
- return { migrated: opsToMigrate.length, skipped: skippedCount, total: validJids.length }
278
- }, `migrate-${validJids.length}-sessions-${WABinary_1.jidDecode(toJid)?.user}`)
279
- },
280
- async encryptMessageWithWire({ encryptionJid, wireJid, data }) {
281
- const result = await repository.encryptMessage({ jid: encryptionJid, data })
282
- return { ...result, wireJid }
311
+ // Single bulk session update for all migrations
312
+ if (Object.keys(sessionUpdates).length > 0) {
313
+ await parsedKeys.set({ session: sessionUpdates })
314
+
315
+ logger.debug({ migratedSessions: migratedCount }, 'bulk session migration complete')
316
+
317
+ // Cache device-level migrations
318
+ for (const op of migrationOps) {
319
+ if (sessionUpdates[op.toAddr.toString()]) {
320
+ const deviceKey = `${op.pnUser}.${op.deviceId}`
321
+ migratedSessionCache.set(deviceKey, true)
322
+ }
323
+ }
324
+ }
325
+
326
+ const skippedCount = totalOps - migratedCount
327
+
328
+ return { migrated: migratedCount, skipped: skippedCount, total: totalOps }
329
+ }, `migrate-${deviceJids.length}-sessions-${jidDecode(toJid)?.user}`)
283
330
  }
284
331
  }
332
+
285
333
  return repository
286
334
  }
287
335
 
288
336
  const jidToSignalProtocolAddress = (jid) => {
289
- const decoded = WABinary_1.jidDecode(jid)
290
- const { user, device, server } = decoded
337
+ const decoded = jidDecode(jid)
338
+ const { user, device, server, domainType } = decoded
291
339
 
292
340
  if (!user) {
293
341
  throw new Error(`JID decoded but user is empty: "${jid}" -> user: "${user}", server: "${server}", device: ${device}`)
294
342
  }
295
343
 
296
- // LID addresses get _1 suffix for Signal protocol
297
- const signalUser = server === 'lid' ? `${user}_1` : user
344
+ const signalUser = domainType !== WAJIDDomains.WHATSAPP ? `${user}_${domainType}` : user
298
345
  const finalDevice = device || 0
299
346
 
300
- return new libsignal.ProtocolAddress(signalUser, finalDevice)
347
+ if (device === 99 && decoded.server !== 'hosted' && decoded.server !== 'hosted.lid') {
348
+ throw new Error('Unexpected non-hosted device JID with device 99. This ID seems invalid. ID:' + jid)
349
+ }
350
+
351
+ return new ProtocolAddress(signalUser, finalDevice)
301
352
  }
302
353
 
303
354
  const jidToSignalSenderKeyName = (group, user) => {
304
- return new sender_key_name_1.SenderKeyName(group, jidToSignalProtocolAddress(user))
355
+ return new SenderKeyName(group, jidToSignalProtocolAddress(user))
305
356
  }
306
357
 
307
358
  function signalStorage({ creds, keys }, lidMapping) {
359
+ // Shared function to resolve PN signal address to LID if mapping exists
360
+ const resolveLIDSignalAddress = async (id) => {
361
+ if (id.includes('.')) {
362
+ const [deviceId, device] = id.split('.')
363
+ const [user, domainType_] = deviceId.split('_')
364
+ const domainType = parseInt(domainType_ || '0')
365
+
366
+ if (domainType === WAJIDDomains.LID || domainType === WAJIDDomains.HOSTED_LID) return id
367
+
368
+ const pnJid = `${user}${device !== '0' ? `:${device}` : ''}@${domainType === WAJIDDomains.HOSTED ? 'hosted' : 's.whatsapp.net'}`
369
+ const lidForPN = await lidMapping.getLIDForPN(pnJid)
370
+
371
+ if (lidForPN) {
372
+ const lidAddr = jidToSignalProtocolAddress(lidForPN)
373
+ return lidAddr.toString()
374
+ }
375
+ }
376
+
377
+ return id
378
+ }
379
+
308
380
  return {
309
381
  loadSession: async (id) => {
310
382
  try {
311
- // LID SINGLE SOURCE OF TRUTH: Auto-redirect PN to LID if mapping exists
312
- let actualId = id
313
- if (id.includes('.') && !id.includes('_1')) {
314
- // This is a PN signal address format (e.g., "1234567890.0")
315
- // Convert back to JID to check for LID mapping
316
- const parts = id.split('.')
317
- const device = parts[1] || '0'
318
- const pnJid = device === '0' ? `${parts[0]}@s.whatsapp.net` : `${parts[0]}:${device}@s.whatsapp.net`
319
- const lidForPN = await lidMapping.getLIDForPN(pnJid)
320
- if (lidForPN?.includes('@lid')) {
321
- const lidAddr = jidToSignalProtocolAddress(lidForPN)
322
- const lidId = lidAddr.toString()
323
- // Check if LID session exists
324
- const { [lidId]: lidSession } = await keys.get('session', [lidId])
325
- if (lidSession) {
326
- actualId = lidId
327
- }
328
- }
329
- }
330
- const { [actualId]: sess } = await keys.get('session', [actualId])
383
+ const wireJid = await resolveLIDSignalAddress(id)
384
+ const { [wireJid]: sess } = await keys.get('session', [wireJid])
385
+
331
386
  if (sess) {
332
- return libsignal.SessionRecord.deserialize(sess)
387
+ return SessionRecord.deserialize(sess)
333
388
  }
334
389
  }
390
+
335
391
  catch (e) {
336
392
  return null
337
393
  }
394
+
338
395
  return null
339
396
  },
340
- // TODO: Replace with libsignal.SessionRecord when type exports are added to libsignal
341
397
  storeSession: async (id, session) => {
342
- await keys.set({ session: { [id]: session.serialize() } })
398
+ const wireJid = await resolveLIDSignalAddress(id)
399
+ await keys.set({ session: { [wireJid]: session.serialize() } })
343
400
  },
344
401
  isTrustedIdentity: () => {
345
- return true
402
+ return true // todo: implement
346
403
  },
347
404
  loadPreKey: async (id) => {
348
405
  const keyId = id.toString()
349
406
  const { [keyId]: key } = await keys.get('pre-key', [keyId])
407
+
350
408
  if (key) {
351
409
  return {
352
410
  privKey: Buffer.from(key.private),
@@ -365,10 +423,12 @@ function signalStorage({ creds, keys }, lidMapping) {
365
423
  loadSenderKey: async (senderKeyName) => {
366
424
  const keyId = senderKeyName.toString()
367
425
  const { [keyId]: key } = await keys.get('sender-key', [keyId])
426
+
368
427
  if (key) {
369
- return sender_key_record_1.SenderKeyRecord.deserialize(key)
428
+ return SenderKeyRecord.deserialize(key)
370
429
  }
371
- return new sender_key_record_1.SenderKeyRecord()
430
+
431
+ return new SenderKeyRecord()
372
432
  },
373
433
  storeSenderKey: async (senderKeyName, key) => {
374
434
  const keyId = senderKeyName.toString()
@@ -380,7 +440,7 @@ function signalStorage({ creds, keys }, lidMapping) {
380
440
  const { signedIdentityKey } = creds
381
441
  return {
382
442
  privKey: Buffer.from(signedIdentityKey.private),
383
- pubKey: Buffer.from(Utils_1.generateSignalPubKey(signedIdentityKey.public))
443
+ pubKey: Buffer.from(generateSignalPubKey(signedIdentityKey.public))
384
444
  }
385
445
  }
386
446
  }