@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,312 +1,362 @@
1
- "use strict"
2
-
3
- Object.defineProperty(exports, "__esModule", { value: true })
4
-
5
- const boom_1 = require("@hapi/boom")
6
- const WAProto_1 = require("../../WAProto")
7
- const WABinary_1 = require("../WABinary")
8
- const generics_1 = require("./generics")
9
- const messages_1 = require("./messages")
10
-
11
- const NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node'
12
-
13
- const MISSING_KEYS_ERROR_TEXT = 'Key used already or never filled'
14
-
15
- // Retry configuration for failed decryption
16
- const DECRYPTION_RETRY_CONFIG = {
17
- maxRetries: 3,
18
- baseDelayMs: 100,
19
- sessionRecordErrors: ['No session record', 'SessionError: No session record']
20
- }
21
-
22
- const NACK_REASONS = {
23
- ParsingError: 487,
24
- UnrecognizedStanza: 488,
25
- UnrecognizedStanzaClass: 489,
26
- UnrecognizedStanzaType: 490,
27
- InvalidProtobuf: 491,
28
- InvalidHostedCompanionStanza: 493,
29
- MissingMessageSecret: 495,
30
- SignalErrorOldCounter: 496,
31
- MessageDeletedOnPeer: 499,
32
- UnhandledError: 500,
33
- UnsupportedAdminRevoke: 550,
34
- UnsupportedLIDGroup: 551,
35
- DBOperationFailed: 552
36
- }
37
-
38
- const extractAddressingContext = (stanza) => {
39
- let senderAlt
40
- let recipientAlt
41
-
42
- const sender = stanza.attrs.participant || stanza.attrs.from
43
- const addressingMode = stanza.attrs.addressing_mode || (sender?.endsWith('lid') ? 'lid' : 'pn')
44
-
45
- if (WABinary_1.isLidUser(sender)) {
46
- // Message is LID-addressed: sender is LID, extract corresponding PN
47
- // without device data
48
- senderAlt = stanza.attrs.participant_pn || stanza.attrs.sender_pn || stanza.attrs.peer_recipient_pn
49
- recipientAlt = stanza.attrs.recipient_pn
50
- // with device data
51
- if (sender && senderAlt)
52
- senderAlt = WABinary_1.transferDevice(sender, senderAlt)
53
- }
54
-
55
- else if (WABinary_1.isJidUser(sender)) {
56
- // Message is PN-addressed: sender is PN, extract corresponding LID
57
- // without device data
58
- senderAlt = stanza.attrs.participant_lid || stanza.attrs.sender_lid || stanza.attrs.peer_recipient_lid
59
- recipientAlt = stanza.attrs.recipient_lid
60
- //with device data
61
- if (sender && senderAlt)
62
- senderAlt = WABinary_1.transferDevice(sender, senderAlt)
63
- }
64
- return {
65
- addressingMode,
66
- senderAlt,
67
- recipientAlt
68
- }
69
- }
70
-
71
- const getDecryptionJid = async (sender, repository) => {
72
- if (!sender.includes('@s.whatsapp.net')) {
73
- return sender
74
- }
75
- return (await repository.lidMapping.getLIDForPN(sender))
76
- }
77
-
78
- const storeMappingFromEnvelope = async (stanza, sender, decryptionJid, repository, logger) => {
79
- const { senderAlt } = extractAddressingContext(stanza)
80
-
81
- if (senderAlt && WABinary_1.isLidUser(senderAlt) && WABinary_1.isJidUser(sender) && decryptionJid === sender) {
82
- try {
83
- await repository.lidMapping.storeLIDPNMappings([{ lid: senderAlt, pn: sender }])
84
- logger.debug({ sender, senderAlt }, 'Stored LID mapping from envelope')
85
- }
86
- catch (error) {
87
- logger.warn({ sender, senderAlt, error }, 'Failed to store LID mapping')
88
- }
89
- }
90
- }
91
-
92
- /**
93
- * Decode the received node as a message.
94
- * @note this will only parse the message, not decrypt it
95
- */
96
- function decodeMessageNode(stanza, meId, meLid) {
97
- let msgType
98
- let chatId
99
- let author
100
- let fromMe = false
101
- const msgId = stanza.attrs.id
102
- const from = stanza.attrs.from
103
- const participant = stanza.attrs.participant
104
- const recipient = stanza.attrs.recipient
105
- const addressingContext = extractAddressingContext(stanza)
106
- const isMe = (jid) => WABinary_1.areJidsSameUser(jid, meId)
107
- const isMeLid = (jid) => WABinary_1.areJidsSameUser(jid, meLid)
108
- if (WABinary_1.isJidUser(from) || WABinary_1.isLidUser(from)) {
109
- if (recipient && !WABinary_1.isJidMetaAI(recipient)) {
110
- if (!isMe(from) && !isMeLid(from)) {
111
- throw new boom_1.Boom('receipient present, but msg not from me', { data: stanza })
112
- }
113
- if (isMe(from) || isMeLid(from)) {
114
- fromMe = true
115
- }
116
- chatId = recipient
117
- }
118
- else {
119
- chatId = from
120
- }
121
- msgType = 'chat'
122
- author = from
123
- }
124
- else if (WABinary_1.isJidGroup(from)) {
125
- if (!participant) {
126
- throw new boom_1.Boom('No participant in group message')
127
- }
128
- if (isMe(participant) || isMeLid(participant)) {
129
- fromMe = true;
130
- }
131
- msgType = 'group'
132
- author = participant
133
- chatId = from
134
- }
135
- else if (WABinary_1.isJidBroadcast(from)) {
136
- if (!participant) {
137
- throw new boom_1.Boom('No participant in group message')
138
- }
139
- const isParticipantMe = isMe(participant)
140
- if (WABinary_1.isJidStatusBroadcast(from)) {
141
- msgType = isParticipantMe ? 'direct_peer_status' : 'other_status'
142
- }
143
- else {
144
- msgType = isParticipantMe ? 'peer_broadcast' : 'other_broadcast'
145
- }
146
- fromMe = isParticipantMe
147
- chatId = from
148
- author = participant
149
- }
150
- else if (WABinary_1.isJidNewsletter(from)) {
151
- msgType = 'newsletter'
152
- chatId = from
153
- author = from
154
- if (isMe(from) || isMeLid(from)) {
155
- fromMe = true;
156
- }
157
- }
158
- else {
159
- throw new boom_1.Boom('Unknown message type', { data: stanza })
160
- }
161
-
162
- const pushname = stanza?.attrs?.notify
163
- const key = {
164
- remoteJid: chatId,
165
- remoteJidAlt: !WABinary_1.isJidGroup(chatId) ? addressingContext.senderAlt : undefined,
166
- fromMe,
167
- id: msgId,
168
- participant,
169
- participantAlt: WABinary_1.isJidGroup(chatId) ? addressingContext.senderAlt : undefined,
170
- }
171
- const fullMessage = {
172
- key,
173
- messageTimestamp: +stanza.attrs.t,
174
- pushName: pushname,
175
- broadcast: WABinary_1.isJidBroadcast(from),
176
- newsletter: WABinary_1.isJidNewsletter(from)
177
- }
178
- if (msgType === 'newsletter') {
179
- fullMessage.newsletter_server_id = +stanza.attrs?.server_id
180
- }
181
- if (key.fromMe) {
182
- fullMessage.status = WAProto_1.proto.WebMessageInfo.Status.SERVER_ACK
183
- }
184
- if (!key.fromMe) {
185
- fullMessage.platform = messages_1.getDevice(key.id)
186
- }
187
- return {
188
- fullMessage,
189
- author,
190
- sender: msgType === 'chat' ? author : chatId
191
- }
192
- }
193
-
194
- const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
195
- const { fullMessage, author, sender } = decodeMessageNode(stanza, meId, meLid)
196
- return {
197
- fullMessage,
198
- category: stanza.attrs.category,
199
- author,
200
- async decrypt() {
201
- let decryptables = 0
202
- if (Array.isArray(stanza.content)) {
203
- for (const { tag, attrs, content } of stanza.content) {
204
- if (tag === 'verified_name' && content instanceof Uint8Array) {
205
- const cert = WAProto_1.proto.VerifiedNameCertificate.decode(content)
206
- const details = WAProto_1.proto.VerifiedNameCertificate.Details.decode(cert.details)
207
- fullMessage.verifiedBizName = details.verifiedName
208
- }
209
- if (tag === 'unavailable' && attrs.type === 'view_once') {
210
- fullMessage.key.isViewOnce = true; // TODO: remove from here and add a STUB TYPE
211
- }
212
- if (tag !== 'enc' && tag !== 'plaintext') {
213
- continue
214
- }
215
- if (!(content instanceof Uint8Array)) {
216
- continue
217
- }
218
- decryptables += 1
219
- let msgBuffer
220
- const user = WABinary_1.isJidUser(sender) ? sender : author // TODO: flaky logic
221
- const decryptionJid = await getDecryptionJid(user, repository)
222
-
223
- if (tag !== 'plaintext') {
224
- await storeMappingFromEnvelope(stanza, user, decryptionJid, repository, logger)
225
- }
226
- try {
227
- const e2eType = tag === 'plaintext' ? 'plaintext' : attrs.type
228
- switch (e2eType) {
229
- case 'skmsg':
230
- msgBuffer = await repository.decryptGroupMessage({
231
- group: sender,
232
- authorJid: author,
233
- msg: content
234
- })
235
- break
236
- case 'pkmsg':
237
- case 'msg':
238
- msgBuffer = await repository.decryptMessage({
239
- jid: decryptionJid,
240
- type: e2eType,
241
- ciphertext: content
242
- })
243
- break
244
- case 'plaintext':
245
- msgBuffer = content
246
- break
247
- default:
248
- throw new Error(`Unknown e2e type: ${e2eType}`)
249
- }
250
- let msg = WAProto_1.proto.Message.decode(e2eType !== 'plaintext' ? generics_1.unpadRandomMax16(msgBuffer) : msgBuffer)
251
- msg = msg.deviceSentMessage?.message || msg
252
- if (msg.senderKeyDistributionMessage) {
253
- //eslint-disable-next-line max-depth
254
- try {
255
- await repository.processSenderKeyDistributionMessage({
256
- authorJid: author,
257
- item: msg.senderKeyDistributionMessage
258
- })
259
- }
260
- catch (err) {
261
- logger.error({ key: fullMessage.key, err }, 'failed to decrypt message')
262
- }
263
- }
264
- if (fullMessage.message) {
265
- Object.assign(fullMessage.message, msg)
266
- }
267
- else {
268
- fullMessage.message = msg
269
- }
270
- }
271
- catch (err) {
272
- const errorContext = {
273
- key: fullMessage.key,
274
- err,
275
- messageType: tag === 'plaintext' ? 'plaintext' : attrs.type,
276
- sender,
277
- author,
278
- isSessionRecordError: isSessionRecordError(err)
279
- }
280
- logger.error(errorContext, 'failed to process sender key distribution message')
281
- fullMessage.messageStubType = WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT
282
- fullMessage.messageStubParameters = [err.message.toString()]
283
- }
284
- }
285
- }
286
-
287
- // if nothing was found to decrypt
288
- if (!decryptables) {
289
- fullMessage.messageStubType = WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT
290
- fullMessage.messageStubParameters = [NO_MESSAGE_FOUND_ERROR_TEXT]
291
- }
292
- }
293
- }
294
- }
295
-
296
- /**
297
- * Utility function to check if an error is related to missing session record
298
- */
299
- function isSessionRecordError(error) {
300
- const errorMessage = error?.message || error?.toString() || ''
301
- return DECRYPTION_RETRY_CONFIG.sessionRecordErrors.some(errorPattern => errorMessage.includes(errorPattern))
302
- }
303
-
304
- module.exports = {
305
- NACK_REASONS,
306
- decodeMessageNode,
307
- decryptMessageNode,
308
- extractAddressingContext,
309
- MISSING_KEYS_ERROR_TEXT,
310
- DECRYPTION_RETRY_CONFIG,
311
- NO_MESSAGE_FOUND_ERROR_TEXT
1
+ "use strict"
2
+
3
+ Object.defineProperty(exports, "__esModule", { value: true })
4
+
5
+ const { Boom } = require("@hapi/boom")
6
+ const { proto } = require("../../WAProto")
7
+ const {
8
+ areJidsSameUser,
9
+ isHostedLidUser,
10
+ isHostedPnUser,
11
+ isJidBroadcast,
12
+ isJidGroup,
13
+ isJidMetaAI,
14
+ isJidNewsletter,
15
+ isJidStatusBroadcast,
16
+ isLidUser,
17
+ isPnUser
18
+ } = require("../WABinary")
19
+ const { unpadRandomMax16 } = require("./generics")
20
+ const { getDevice } = require("./messages")
21
+
22
+ const NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node'
23
+
24
+ const MISSING_KEYS_ERROR_TEXT = 'Key used already or never filled'
25
+
26
+ // Retry configuration for failed decryption
27
+ const DECRYPTION_RETRY_CONFIG = {
28
+ maxRetries: 3,
29
+ baseDelayMs: 100,
30
+ sessionRecordErrors: ['No session record', 'SessionError: No session record']
31
+ }
32
+
33
+ const NACK_REASONS = {
34
+ ParsingError: 487,
35
+ UnrecognizedStanza: 488,
36
+ UnrecognizedStanzaClass: 489,
37
+ UnrecognizedStanzaType: 490,
38
+ InvalidProtobuf: 491,
39
+ InvalidHostedCompanionStanza: 493,
40
+ MissingMessageSecret: 495,
41
+ SignalErrorOldCounter: 496,
42
+ MessageDeletedOnPeer: 499,
43
+ UnhandledError: 500,
44
+ UnsupportedAdminRevoke: 550,
45
+ UnsupportedLIDGroup: 551,
46
+ DBOperationFailed: 552
47
+ }
48
+
49
+ const extractAddressingContext = (stanza) => {
50
+ let senderAlt
51
+ let recipientAlt
52
+
53
+ const sender = stanza.attrs.participant || stanza.attrs.from
54
+ const addressingMode = stanza.attrs.addressing_mode || (sender?.endsWith('lid') ? 'lid' : 'pn')
55
+
56
+ if (addressingMode === 'lid') {
57
+ // Message is LID-addressed: sender is LID, extract corresponding PN
58
+ // without device data
59
+ senderAlt = stanza.attrs.participant_pn || stanza.attrs.sender_pn || stanza.attrs.peer_recipient_pn
60
+ recipientAlt = stanza.attrs.recipient_pn
61
+ // with device data
62
+ //if (sender && senderAlt) senderAlt = transferDevice(sender, senderAlt)
63
+ }
64
+ else {
65
+ // Message is PN-addressed: sender is PN, extract corresponding LID
66
+ // without device data
67
+ senderAlt = stanza.attrs.participant_lid || stanza.attrs.sender_lid || stanza.attrs.peer_recipient_lid
68
+ recipientAlt = stanza.attrs.recipient_lid
69
+ //with device data
70
+ //if (sender && senderAlt) senderAlt = transferDevice(sender, senderAlt)
71
+ }
72
+
73
+ return {
74
+ addressingMode,
75
+ senderAlt,
76
+ recipientAlt
77
+ }
78
+ }
79
+
80
+ const getDecryptionJid = async (sender, repository) => {
81
+ if (isLidUser(sender) || isHostedLidUser(sender)) {
82
+ return sender
83
+ }
84
+ const mapped = await repository.lidMapping.getLIDForPN(sender)
85
+ return mapped || sender
86
+ }
87
+
88
+ const storeMappingFromEnvelope = async (stanza, sender, repository, decryptionJid, logger) => {
89
+ // TODO: Handle hosted IDs
90
+ const { senderAlt } = extractAddressingContext(stanza)
91
+
92
+ if (senderAlt && isLidUser(senderAlt) && isPnUser(sender) && decryptionJid === sender) {
93
+ try {
94
+ await repository.lidMapping.storeLIDPNMappings([{ lid: senderAlt, pn: sender }])
95
+ await repository.migrateSession(sender, senderAlt)
96
+ logger.debug({ sender, senderAlt }, 'Stored LID mapping from envelope')
97
+ }
98
+ catch (error) {
99
+ logger.warn({ sender, senderAlt, error }, 'Failed to store LID mapping')
100
+ }
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Decode the received node as a message.
106
+ * @note this will only parse the message, not decrypt it
107
+ */
108
+ function decodeMessageNode(stanza, meId, meLid) {
109
+ let msgType
110
+ let chatId
111
+ let author
112
+ let fromMe = false
113
+
114
+ const msgId = stanza.attrs.id
115
+ const from = stanza.attrs.from
116
+ const participant = stanza.attrs.participant
117
+ const recipient = stanza.attrs.recipient
118
+ const addressingContext = extractAddressingContext(stanza)
119
+ const isMe = (jid) => areJidsSameUser(jid, meId)
120
+ const isMeLid = (jid) => areJidsSameUser(jid, meLid)
121
+
122
+ if (isPnUser(from) || isLidUser(from) || isHostedLidUser(from) || isHostedPnUser(from)) {
123
+ if (recipient && !isJidMetaAI(recipient)) {
124
+ if (!isMe(from) && !isMeLid(from)) {
125
+ throw new Boom('receipient present, but msg not from me', { data: stanza })
126
+ }
127
+
128
+ if (isMe(from) || isMeLid(from)) {
129
+ fromMe = true
130
+ }
131
+
132
+ chatId = recipient
133
+ }
134
+ else {
135
+ chatId = from
136
+ }
137
+
138
+ msgType = 'chat'
139
+ author = from
140
+ }
141
+
142
+ else if (isJidGroup(from)) {
143
+ if (!participant) {
144
+ throw new Boom('No participant in group message')
145
+ }
146
+
147
+ if (isMe(participant) || isMeLid(participant)) {
148
+ fromMe = true
149
+ }
150
+
151
+ msgType = 'group'
152
+ author = participant
153
+ chatId = from
154
+ }
155
+
156
+ else if (isJidBroadcast(from)) {
157
+ if (!participant) {
158
+ throw new Boom('No participant in group message')
159
+ }
160
+
161
+ const isParticipantMe = isMe(participant)
162
+
163
+ if (isJidStatusBroadcast(from)) {
164
+ msgType = isParticipantMe ? 'direct_peer_status' : 'other_status'
165
+ }
166
+
167
+ else {
168
+ msgType = isParticipantMe ? 'peer_broadcast' : 'other_broadcast'
169
+ }
170
+
171
+ fromMe = isParticipantMe
172
+ chatId = from
173
+ author = participant
174
+ }
175
+
176
+ else if (isJidNewsletter(from)) {
177
+ msgType = 'newsletter'
178
+ chatId = from
179
+ author = from
180
+
181
+ if (isMe(from) || isMeLid(from)) {
182
+ fromMe = true
183
+ }
184
+ }
185
+
186
+ else {
187
+ throw new Boom('Unknown message type', { data: stanza })
188
+ }
189
+
190
+ const pushname = stanza?.attrs?.notify
191
+
192
+ const key = {
193
+ remoteJid: chatId,
194
+ remoteJidAlt: !isJidGroup(chatId) ? addressingContext.senderAlt : undefined,
195
+ fromMe,
196
+ id: msgId,
197
+ participant,
198
+ participantAlt: isJidGroup(chatId) ? addressingContext.senderAlt : undefined,
199
+ addressingMode: addressingContext.addressingMode,
200
+ ...(msgType === 'newsletter' && stanza.attrs.server_id ? { server_id: stanza.attrs.server_id } : {})
201
+ }
202
+
203
+ const fullMessage = {
204
+ key,
205
+ category: stanza.attrs.category,
206
+ messageTimestamp: +stanza.attrs.t,
207
+ pushName: pushname,
208
+ platform: getDevice(key.id),
209
+ broadcast: isJidBroadcast(from),
210
+ newsletter: isJidNewsletter(from)
211
+ }
212
+
213
+ if (key.fromMe) {
214
+ fullMessage.status = proto.WebMessageInfo.Status.SERVER_ACK
215
+ }
216
+
217
+ return {
218
+ fullMessage,
219
+ author,
220
+ sender: msgType === 'chat' ? author : chatId
221
+ }
222
+ }
223
+
224
+ const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
225
+ const { fullMessage, author, sender } = decodeMessageNode(stanza, meId, meLid)
226
+ return {
227
+ fullMessage,
228
+ category: stanza.attrs.category,
229
+ author,
230
+ async decrypt() {
231
+ let decryptables = 0
232
+
233
+ if (Array.isArray(stanza.content)) {
234
+ for (const { tag, attrs, content } of stanza.content) {
235
+ if (tag === 'verified_name' && content instanceof Uint8Array) {
236
+ const cert = proto.VerifiedNameCertificate.decode(content)
237
+ const details = proto.VerifiedNameCertificate.Details.decode(cert.details)
238
+
239
+ fullMessage.verifiedBizName = details.verifiedName
240
+ }
241
+
242
+ if (tag === 'unavailable' && attrs.type === 'view_once') {
243
+ fullMessage.key.isViewOnce = true // TODO: remove from here and add a STUB TYPE
244
+ }
245
+
246
+ if (attrs.count && tag === 'enc') {
247
+ fullMessage.retryCount = Number(attrs.count)
248
+ }
249
+
250
+ if (tag !== 'enc' && tag !== 'plaintext') {
251
+ continue
252
+ }
253
+
254
+ if (!(content instanceof Uint8Array)) {
255
+ continue
256
+ }
257
+
258
+ decryptables += 1
259
+
260
+ let msgBuffer
261
+
262
+ const decryptionJid = await getDecryptionJid(author, repository)
263
+
264
+ if (tag !== 'plaintext') {
265
+ // TODO: Handle hosted devices
266
+ await storeMappingFromEnvelope(stanza, author, repository, decryptionJid, logger)
267
+ }
268
+
269
+ try {
270
+ const e2eType = tag === 'plaintext' ? 'plaintext' : attrs.type
271
+ switch (e2eType) {
272
+ case 'skmsg':
273
+ msgBuffer = await repository.decryptGroupMessage({
274
+ group: sender,
275
+ authorJid: author,
276
+ msg: content
277
+ })
278
+ break
279
+ case 'pkmsg':
280
+ case 'msg':
281
+ msgBuffer = await repository.decryptMessage({
282
+ jid: decryptionJid,
283
+ type: e2eType,
284
+ ciphertext: content
285
+ })
286
+ break
287
+ case 'plaintext':
288
+ msgBuffer = content
289
+ break
290
+ default:
291
+ throw new Error(`Unknown e2e type: ${e2eType}`)
292
+ }
293
+
294
+ let msg = proto.Message.decode(e2eType !== 'plaintext' ? unpadRandomMax16(msgBuffer) : msgBuffer)
295
+
296
+ msg = msg.deviceSentMessage?.message || msg
297
+
298
+ if (msg.senderKeyDistributionMessage) {
299
+ try {
300
+ await repository.processSenderKeyDistributionMessage({
301
+ authorJid: author,
302
+ item: msg.senderKeyDistributionMessage
303
+ })
304
+ }
305
+
306
+ catch (err) {
307
+ logger.error({ key: fullMessage.key, err }, 'failed to process sender key distribution message')
308
+ }
309
+ }
310
+
311
+ if (fullMessage.message) {
312
+ Object.assign(fullMessage.message, msg)
313
+ }
314
+
315
+ else {
316
+ fullMessage.message = msg
317
+ }
318
+ }
319
+
320
+ catch (err) {
321
+ const errorContext = {
322
+ key: fullMessage.key,
323
+ err,
324
+ messageType: tag === 'plaintext' ? 'plaintext' : attrs.type,
325
+ sender,
326
+ author,
327
+ isSessionRecordError: isSessionRecordError(err)
328
+ }
329
+
330
+ logger.error(errorContext, 'failed to decrypt message')
331
+ fullMessage.messageStubType = proto.WebMessageInfo.StubType.CIPHERTEXT
332
+ fullMessage.messageStubParameters = [err.message.toString()]
333
+ }
334
+ }
335
+ }
336
+
337
+ // if nothing was found to decrypt
338
+ if (!decryptables && !fullMessage.key?.isViewOnce) {
339
+ fullMessage.messageStubType = proto.WebMessageInfo.StubType.CIPHERTEXT
340
+ fullMessage.messageStubParameters = [NO_MESSAGE_FOUND_ERROR_TEXT]
341
+ }
342
+ }
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Utility function to check if an error is related to missing session record
348
+ */
349
+ function isSessionRecordError(error) {
350
+ const errorMessage = error?.message || error?.toString() || ''
351
+ return DECRYPTION_RETRY_CONFIG.sessionRecordErrors.some(errorPattern => errorMessage.includes(errorPattern))
352
+ }
353
+
354
+ module.exports = {
355
+ NACK_REASONS,
356
+ decodeMessageNode,
357
+ decryptMessageNode,
358
+ extractAddressingContext,
359
+ MISSING_KEYS_ERROR_TEXT,
360
+ DECRYPTION_RETRY_CONFIG,
361
+ NO_MESSAGE_FOUND_ERROR_TEXT
312
362
  }