phantom-baileys 0.0.8 → 0.1.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 (441) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +592 -0
  3. package/WAProto/GenerateStatics.sh +3 -0
  4. package/WAProto/WAProto.proto +5479 -0
  5. package/WAProto/fix-imports.js +81 -0
  6. package/WAProto/index.d.ts +5147 -41513
  7. package/WAProto/index.js +84008 -142014
  8. package/lib/Defaults/index.d.ts +29 -8
  9. package/lib/Defaults/index.d.ts.map +1 -0
  10. package/lib/Defaults/index.js +80 -60
  11. package/lib/Defaults/index.js.map +1 -0
  12. package/lib/Signal/Group/ciphertext-message.d.ts +10 -0
  13. package/lib/Signal/Group/ciphertext-message.d.ts.map +1 -0
  14. package/lib/Signal/Group/ciphertext-message.js +12 -0
  15. package/lib/Signal/Group/ciphertext-message.js.map +1 -0
  16. package/lib/Signal/Group/group-session-builder.d.ts +15 -0
  17. package/lib/Signal/Group/group-session-builder.d.ts.map +1 -0
  18. package/lib/Signal/Group/group-session-builder.js +30 -0
  19. package/lib/Signal/Group/group-session-builder.js.map +1 -0
  20. package/lib/Signal/Group/group_cipher.d.ts +17 -0
  21. package/lib/Signal/Group/group_cipher.d.ts.map +1 -0
  22. package/lib/Signal/Group/group_cipher.js +82 -0
  23. package/lib/Signal/Group/group_cipher.js.map +1 -0
  24. package/lib/Signal/Group/index.d.ts +12 -0
  25. package/lib/Signal/Group/index.d.ts.map +1 -0
  26. package/lib/Signal/Group/index.js +12 -0
  27. package/lib/Signal/Group/index.js.map +1 -0
  28. package/lib/Signal/Group/keyhelper.d.ts +11 -0
  29. package/lib/Signal/Group/keyhelper.d.ts.map +1 -0
  30. package/lib/Signal/Group/keyhelper.js +18 -0
  31. package/lib/Signal/Group/keyhelper.js.map +1 -0
  32. package/lib/Signal/Group/sender-chain-key.d.ts +14 -0
  33. package/lib/Signal/Group/sender-chain-key.d.ts.map +1 -0
  34. package/lib/Signal/Group/sender-chain-key.js +26 -0
  35. package/lib/Signal/Group/sender-chain-key.js.map +1 -0
  36. package/lib/Signal/Group/sender-key-distribution-message.d.ts +17 -0
  37. package/lib/Signal/Group/sender-key-distribution-message.d.ts.map +1 -0
  38. package/lib/Signal/Group/sender-key-distribution-message.js +63 -0
  39. package/lib/Signal/Group/sender-key-distribution-message.js.map +1 -0
  40. package/lib/Signal/Group/sender-key-message.d.ts +19 -0
  41. package/lib/Signal/Group/sender-key-message.d.ts.map +1 -0
  42. package/lib/Signal/Group/sender-key-message.js +66 -0
  43. package/lib/Signal/Group/sender-key-message.js.map +1 -0
  44. package/lib/Signal/Group/sender-key-name.d.ts +18 -0
  45. package/lib/Signal/Group/sender-key-name.d.ts.map +1 -0
  46. package/lib/Signal/Group/sender-key-name.js +48 -0
  47. package/lib/Signal/Group/sender-key-name.js.map +1 -0
  48. package/lib/Signal/Group/sender-key-record.d.ts +31 -0
  49. package/lib/Signal/Group/sender-key-record.d.ts.map +1 -0
  50. package/lib/Signal/Group/sender-key-record.js +41 -0
  51. package/lib/Signal/Group/sender-key-record.js.map +1 -0
  52. package/lib/Signal/Group/sender-key-state.d.ts +39 -0
  53. package/lib/Signal/Group/sender-key-state.d.ts.map +1 -0
  54. package/lib/Signal/Group/sender-key-state.js +84 -0
  55. package/lib/Signal/Group/sender-key-state.js.map +1 -0
  56. package/lib/Signal/Group/sender-message-key.d.ts +12 -0
  57. package/lib/Signal/Group/sender-message-key.d.ts.map +1 -0
  58. package/{WASignalGroup/sender_message_key.js → lib/Signal/Group/sender-message-key.js} +3 -16
  59. package/lib/Signal/Group/sender-message-key.js.map +1 -0
  60. package/lib/Signal/libsignal.d.ts +5 -3
  61. package/lib/Signal/libsignal.d.ts.map +1 -0
  62. package/lib/Signal/libsignal.js +331 -80
  63. package/lib/Signal/libsignal.js.map +1 -0
  64. package/lib/Signal/lid-mapping.d.ts +19 -0
  65. package/lib/Signal/lid-mapping.d.ts.map +1 -0
  66. package/lib/Signal/lid-mapping.js +271 -0
  67. package/lib/Signal/lid-mapping.js.map +1 -0
  68. package/lib/Socket/Client/index.d.ts +3 -3
  69. package/lib/Socket/Client/index.d.ts.map +1 -0
  70. package/lib/Socket/Client/index.js +3 -19
  71. package/lib/Socket/Client/index.js.map +1 -0
  72. package/lib/Socket/Client/{abstract-socket-client.d.ts → types.d.ts} +4 -5
  73. package/lib/Socket/Client/types.d.ts.map +1 -0
  74. package/lib/Socket/Client/types.js +11 -0
  75. package/lib/Socket/Client/types.js.map +1 -0
  76. package/lib/Socket/Client/{web-socket-client.d.ts → websocket.d.ts} +3 -2
  77. package/lib/Socket/Client/websocket.d.ts.map +1 -0
  78. package/lib/Socket/Client/websocket.js +54 -0
  79. package/lib/Socket/Client/websocket.js.map +1 -0
  80. package/lib/Socket/business.d.ts +184 -101
  81. package/lib/Socket/business.d.ts.map +1 -0
  82. package/lib/Socket/business.js +162 -43
  83. package/lib/Socket/business.js.map +1 -0
  84. package/lib/Socket/chats.d.ts +72 -42
  85. package/lib/Socket/chats.d.ts.map +1 -0
  86. package/lib/Socket/chats.js +340 -299
  87. package/lib/Socket/chats.js.map +1 -0
  88. package/lib/Socket/communities.d.ts +309 -0
  89. package/lib/Socket/communities.d.ts.map +1 -0
  90. package/lib/Socket/communities.js +431 -0
  91. package/lib/Socket/communities.js.map +1 -0
  92. package/lib/Socket/dugong.d.ts +79 -0
  93. package/lib/Socket/dugong.d.ts.map +1 -0
  94. package/lib/Socket/dugong.js +527 -0
  95. package/lib/Socket/dugong.js.map +1 -0
  96. package/lib/Socket/groups.d.ts +93 -58
  97. package/lib/Socket/groups.d.ts.map +1 -0
  98. package/lib/Socket/groups.js +96 -84
  99. package/lib/Socket/groups.js.map +1 -0
  100. package/lib/Socket/index.d.ts +232 -107
  101. package/lib/Socket/index.d.ts.map +1 -0
  102. package/lib/Socket/index.js +13 -10
  103. package/lib/Socket/index.js.map +1 -0
  104. package/lib/Socket/messages-recv.d.ts +170 -90
  105. package/lib/Socket/messages-recv.d.ts.map +1 -0
  106. package/lib/Socket/messages-recv.js +798 -462
  107. package/lib/Socket/messages-recv.js.map +1 -0
  108. package/lib/Socket/messages-send.d.ts +180 -99
  109. package/lib/Socket/messages-send.d.ts.map +1 -0
  110. package/lib/Socket/messages-send.js +833 -709
  111. package/lib/Socket/messages-send.js.map +1 -0
  112. package/lib/Socket/mex.d.ts +3 -0
  113. package/lib/Socket/mex.d.ts.map +1 -0
  114. package/lib/Socket/mex.js +42 -0
  115. package/lib/Socket/mex.js.map +1 -0
  116. package/lib/Socket/newsletter.d.ts +120 -75
  117. package/lib/Socket/newsletter.d.ts.map +1 -0
  118. package/lib/Socket/newsletter.js +227 -198
  119. package/lib/Socket/newsletter.js.map +1 -0
  120. package/lib/Socket/socket.d.ts +31 -20
  121. package/lib/Socket/socket.d.ts.map +1 -0
  122. package/lib/Socket/socket.js +508 -215
  123. package/lib/Socket/socket.js.map +1 -0
  124. package/lib/Types/Auth.d.ts +18 -11
  125. package/lib/Types/Auth.d.ts.map +1 -0
  126. package/lib/Types/Auth.js +2 -2
  127. package/lib/Types/Auth.js.map +1 -0
  128. package/lib/Types/Bussines.d.ts +25 -0
  129. package/lib/Types/Bussines.d.ts.map +1 -0
  130. package/lib/Types/Bussines.js +2 -0
  131. package/lib/Types/Bussines.js.map +1 -0
  132. package/lib/Types/Call.d.ts +2 -0
  133. package/lib/Types/Call.d.ts.map +1 -0
  134. package/lib/Types/Call.js +2 -2
  135. package/lib/Types/Call.js.map +1 -0
  136. package/lib/Types/Chat.d.ts +24 -8
  137. package/lib/Types/Chat.d.ts.map +1 -0
  138. package/lib/Types/Chat.js +8 -4
  139. package/lib/Types/Chat.js.map +1 -0
  140. package/lib/Types/Contact.d.ts +6 -1
  141. package/lib/Types/Contact.d.ts.map +1 -0
  142. package/lib/Types/Contact.js +2 -2
  143. package/lib/Types/Contact.js.map +1 -0
  144. package/lib/Types/Events.d.ts +82 -17
  145. package/lib/Types/Events.d.ts.map +1 -0
  146. package/lib/Types/Events.js +2 -2
  147. package/lib/Types/Events.js.map +1 -0
  148. package/lib/Types/GroupMetadata.d.ts +15 -3
  149. package/lib/Types/GroupMetadata.d.ts.map +1 -0
  150. package/lib/Types/GroupMetadata.js +2 -2
  151. package/lib/Types/GroupMetadata.js.map +1 -0
  152. package/lib/Types/Label.d.ts +1 -0
  153. package/lib/Types/Label.d.ts.map +1 -0
  154. package/lib/Types/Label.js +3 -5
  155. package/lib/Types/Label.js.map +1 -0
  156. package/lib/Types/LabelAssociation.d.ts +1 -0
  157. package/lib/Types/LabelAssociation.d.ts.map +1 -0
  158. package/lib/Types/LabelAssociation.js +3 -5
  159. package/lib/Types/LabelAssociation.js.map +1 -0
  160. package/lib/Types/Message.d.ts +77 -202
  161. package/lib/Types/Message.d.ts.map +1 -0
  162. package/lib/Types/Message.js +11 -9
  163. package/lib/Types/Message.js.map +1 -0
  164. package/lib/Types/Newsletter.d.ts +128 -85
  165. package/lib/Types/Newsletter.d.ts.map +1 -0
  166. package/lib/Types/Newsletter.js +25 -26
  167. package/lib/Types/Newsletter.js.map +1 -0
  168. package/lib/Types/Product.d.ts +2 -1
  169. package/lib/Types/Product.d.ts.map +1 -0
  170. package/lib/Types/Product.js +2 -2
  171. package/lib/Types/Product.js.map +1 -0
  172. package/lib/Types/Signal.d.ts +20 -1
  173. package/lib/Types/Signal.d.ts.map +1 -0
  174. package/lib/Types/Signal.js +2 -2
  175. package/lib/Types/Signal.js.map +1 -0
  176. package/lib/Types/Socket.d.ts +41 -24
  177. package/lib/Types/Socket.d.ts.map +1 -0
  178. package/lib/Types/Socket.js +3 -2
  179. package/lib/Types/Socket.js.map +1 -0
  180. package/lib/Types/State.d.ts +14 -2
  181. package/lib/Types/State.d.ts.map +1 -0
  182. package/lib/Types/State.js +13 -2
  183. package/lib/Types/State.js.map +1 -0
  184. package/lib/Types/USync.d.ts +3 -2
  185. package/lib/Types/USync.d.ts.map +1 -0
  186. package/lib/Types/USync.js +2 -2
  187. package/lib/Types/USync.js.map +1 -0
  188. package/lib/Types/index.d.ts +15 -16
  189. package/lib/Types/index.d.ts.map +1 -0
  190. package/lib/Types/index.js +15 -31
  191. package/lib/Types/index.js.map +1 -0
  192. package/lib/Utils/auth-utils.d.ts +7 -6
  193. package/lib/Utils/auth-utils.d.ts.map +1 -0
  194. package/lib/Utils/auth-utils.js +228 -165
  195. package/lib/Utils/auth-utils.js.map +1 -0
  196. package/lib/Utils/browser-utils.d.ts +4 -0
  197. package/lib/Utils/browser-utils.d.ts.map +1 -0
  198. package/lib/Utils/browser-utils.js +28 -0
  199. package/lib/Utils/browser-utils.js.map +1 -0
  200. package/lib/Utils/business.d.ts +4 -3
  201. package/lib/Utils/business.d.ts.map +1 -0
  202. package/lib/Utils/business.js +66 -69
  203. package/lib/Utils/business.js.map +1 -0
  204. package/lib/Utils/chat-utils.d.ts +16 -16
  205. package/lib/Utils/chat-utils.d.ts.map +1 -0
  206. package/lib/Utils/chat-utils.js +299 -232
  207. package/lib/Utils/chat-utils.js.map +1 -0
  208. package/lib/Utils/crypto.d.ts +18 -21
  209. package/lib/Utils/crypto.d.ts.map +1 -0
  210. package/lib/Utils/crypto.js +44 -125
  211. package/lib/Utils/crypto.js.map +1 -0
  212. package/lib/Utils/decode-wa-message.d.ts +20 -8
  213. package/lib/Utils/decode-wa-message.d.ts.map +1 -0
  214. package/lib/Utils/decode-wa-message.js +139 -90
  215. package/lib/Utils/decode-wa-message.js.map +1 -0
  216. package/lib/Utils/event-buffer.d.ts +7 -8
  217. package/lib/Utils/event-buffer.d.ts.map +1 -0
  218. package/lib/Utils/event-buffer.js +129 -72
  219. package/lib/Utils/event-buffer.js.map +1 -0
  220. package/lib/Utils/generics.d.ts +25 -22
  221. package/lib/Utils/generics.d.ts.map +1 -0
  222. package/lib/Utils/generics.js +157 -175
  223. package/lib/Utils/generics.js.map +1 -0
  224. package/lib/Utils/history.d.ts +14 -11
  225. package/lib/Utils/history.d.ts.map +1 -0
  226. package/lib/Utils/history.js +83 -46
  227. package/lib/Utils/history.js.map +1 -0
  228. package/lib/Utils/identity-change-handler.d.ts +37 -0
  229. package/lib/Utils/identity-change-handler.d.ts.map +1 -0
  230. package/lib/Utils/identity-change-handler.js +49 -0
  231. package/lib/Utils/identity-change-handler.js.map +1 -0
  232. package/lib/Utils/index.d.ts +22 -17
  233. package/lib/Utils/index.d.ts.map +1 -0
  234. package/lib/Utils/index.js +22 -33
  235. package/lib/Utils/index.js.map +1 -0
  236. package/lib/Utils/link-preview.d.ts +5 -5
  237. package/lib/Utils/link-preview.d.ts.map +1 -0
  238. package/lib/Utils/link-preview.js +14 -22
  239. package/lib/Utils/link-preview.js.map +1 -0
  240. package/lib/Utils/logger.d.ts +12 -1
  241. package/lib/Utils/logger.d.ts.map +1 -0
  242. package/lib/Utils/logger.js +3 -7
  243. package/lib/Utils/logger.js.map +1 -0
  244. package/lib/Utils/lt-hash.d.ts +8 -12
  245. package/lib/Utils/lt-hash.d.ts.map +1 -0
  246. package/lib/Utils/lt-hash.js +3 -46
  247. package/lib/Utils/lt-hash.js.map +1 -0
  248. package/lib/Utils/make-mutex.d.ts +2 -0
  249. package/lib/Utils/make-mutex.d.ts.map +1 -0
  250. package/lib/Utils/make-mutex.js +24 -34
  251. package/lib/Utils/make-mutex.js.map +1 -0
  252. package/lib/Utils/message-retry-manager.d.ts +110 -0
  253. package/lib/Utils/message-retry-manager.d.ts.map +1 -0
  254. package/lib/Utils/message-retry-manager.js +225 -0
  255. package/lib/Utils/message-retry-manager.js.map +1 -0
  256. package/lib/Utils/messages-media.d.ts +59 -42
  257. package/lib/Utils/messages-media.d.ts.map +1 -0
  258. package/lib/Utils/messages-media.js +411 -356
  259. package/lib/Utils/messages-media.js.map +1 -0
  260. package/lib/Utils/messages.d.ts +32 -18
  261. package/lib/Utils/messages.d.ts.map +1 -0
  262. package/lib/Utils/messages.js +412 -723
  263. package/lib/Utils/messages.js.map +1 -0
  264. package/lib/Utils/noise-handler.d.ts +13 -13
  265. package/lib/Utils/noise-handler.d.ts.map +1 -0
  266. package/lib/Utils/noise-handler.js +149 -108
  267. package/lib/Utils/noise-handler.js.map +1 -0
  268. package/lib/Utils/offline-node-processor.d.ts +17 -0
  269. package/lib/Utils/offline-node-processor.d.ts.map +1 -0
  270. package/lib/Utils/offline-node-processor.js +40 -0
  271. package/lib/Utils/offline-node-processor.js.map +1 -0
  272. package/lib/Utils/pre-key-manager.d.ts +28 -0
  273. package/lib/Utils/pre-key-manager.d.ts.map +1 -0
  274. package/lib/Utils/pre-key-manager.js +106 -0
  275. package/lib/Utils/pre-key-manager.js.map +1 -0
  276. package/lib/Utils/process-message.d.ts +30 -11
  277. package/lib/Utils/process-message.d.ts.map +1 -0
  278. package/lib/Utils/process-message.js +321 -166
  279. package/lib/Utils/process-message.js.map +1 -0
  280. package/lib/Utils/reporting-utils.d.ts +11 -0
  281. package/lib/Utils/reporting-utils.d.ts.map +1 -0
  282. package/lib/Utils/reporting-utils.js +258 -0
  283. package/lib/Utils/reporting-utils.js.map +1 -0
  284. package/lib/Utils/rich-messages.d.ts +129 -0
  285. package/lib/Utils/rich-messages.d.ts.map +1 -0
  286. package/lib/Utils/rich-messages.js +455 -0
  287. package/lib/Utils/rich-messages.js.map +1 -0
  288. package/lib/Utils/signal.d.ts +7 -6
  289. package/lib/Utils/signal.d.ts.map +1 -0
  290. package/lib/Utils/signal.js +65 -65
  291. package/lib/Utils/signal.js.map +1 -0
  292. package/lib/Utils/stanza-ack.d.ts +11 -0
  293. package/lib/Utils/stanza-ack.d.ts.map +1 -0
  294. package/lib/Utils/stanza-ack.js +38 -0
  295. package/lib/Utils/stanza-ack.js.map +1 -0
  296. package/lib/Utils/sync-action-utils.d.ts +19 -0
  297. package/lib/Utils/sync-action-utils.d.ts.map +1 -0
  298. package/lib/Utils/sync-action-utils.js +48 -0
  299. package/lib/Utils/sync-action-utils.js.map +1 -0
  300. package/lib/Utils/tc-token-utils.d.ts +12 -0
  301. package/lib/Utils/tc-token-utils.d.ts.map +1 -0
  302. package/lib/Utils/tc-token-utils.js +18 -0
  303. package/lib/Utils/tc-token-utils.js.map +1 -0
  304. package/lib/Utils/use-multi-file-auth-state.d.ts +2 -1
  305. package/lib/Utils/use-multi-file-auth-state.d.ts.map +1 -0
  306. package/lib/Utils/use-multi-file-auth-state.js +79 -253
  307. package/lib/Utils/use-multi-file-auth-state.js.map +1 -0
  308. package/lib/Utils/validate-connection.d.ts +6 -6
  309. package/lib/Utils/validate-connection.d.ts.map +1 -0
  310. package/lib/Utils/validate-connection.js +111 -116
  311. package/lib/Utils/validate-connection.js.map +1 -0
  312. package/lib/WABinary/constants.d.ts +5 -4
  313. package/lib/WABinary/constants.d.ts.map +1 -0
  314. package/lib/WABinary/constants.js +1281 -20
  315. package/lib/WABinary/constants.js.map +1 -0
  316. package/lib/WABinary/decode.d.ts +4 -3
  317. package/lib/WABinary/decode.d.ts.map +1 -0
  318. package/lib/WABinary/decode.js +51 -53
  319. package/lib/WABinary/decode.js.map +1 -0
  320. package/lib/WABinary/encode.d.ts +2 -1
  321. package/lib/WABinary/encode.d.ts.map +1 -0
  322. package/lib/WABinary/encode.js +12 -44
  323. package/lib/WABinary/encode.js.map +1 -0
  324. package/lib/WABinary/generic-utils.d.ts +9 -6
  325. package/lib/WABinary/generic-utils.d.ts.map +1 -0
  326. package/lib/WABinary/generic-utils.js +124 -43
  327. package/lib/WABinary/generic-utils.js.map +1 -0
  328. package/lib/WABinary/index.d.ts +6 -5
  329. package/lib/WABinary/index.d.ts.map +1 -0
  330. package/lib/WABinary/index.js +6 -21
  331. package/lib/WABinary/index.js.map +1 -0
  332. package/lib/WABinary/jid-utils.d.ts +24 -7
  333. package/lib/WABinary/jid-utils.d.ts.map +1 -0
  334. package/lib/WABinary/jid-utils.js +74 -40
  335. package/lib/WABinary/jid-utils.js.map +1 -0
  336. package/lib/WABinary/types.d.ts +2 -1
  337. package/lib/WABinary/types.d.ts.map +1 -0
  338. package/lib/WABinary/types.js +2 -2
  339. package/lib/WABinary/types.js.map +1 -0
  340. package/lib/WAM/BinaryInfo.d.ts +2 -1
  341. package/lib/WAM/BinaryInfo.d.ts.map +1 -0
  342. package/lib/WAM/BinaryInfo.js +2 -5
  343. package/lib/WAM/BinaryInfo.js.map +1 -0
  344. package/lib/WAM/constants.d.ts +5 -3
  345. package/lib/WAM/constants.d.ts.map +1 -0
  346. package/lib/WAM/constants.js +19071 -11568
  347. package/lib/WAM/constants.js.map +1 -0
  348. package/lib/WAM/encode.d.ts +3 -2
  349. package/lib/WAM/encode.d.ts.map +1 -0
  350. package/lib/WAM/encode.js +17 -22
  351. package/lib/WAM/encode.js.map +1 -0
  352. package/lib/WAM/index.d.ts +4 -3
  353. package/lib/WAM/index.d.ts.map +1 -0
  354. package/lib/WAM/index.js +4 -19
  355. package/lib/WAM/index.js.map +1 -0
  356. package/lib/WAProto/fix-imports.d.ts +1 -0
  357. package/lib/WAProto/fix-imports.js +71 -0
  358. package/lib/WAProto/index.js +89345 -0
  359. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +4 -3
  360. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -0
  361. package/lib/WAUSync/Protocols/USyncContactProtocol.js +8 -11
  362. package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -0
  363. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +3 -2
  364. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +1 -0
  365. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +11 -14
  366. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +1 -0
  367. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +3 -2
  368. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +1 -0
  369. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +9 -12
  370. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +1 -0
  371. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +3 -2
  372. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +1 -0
  373. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +9 -13
  374. package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +1 -0
  375. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +4 -3
  376. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts.map +1 -0
  377. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +20 -22
  378. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js.map +1 -0
  379. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +5 -3
  380. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +1 -0
  381. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +13 -8
  382. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +1 -0
  383. package/lib/WAUSync/Protocols/index.d.ts +5 -4
  384. package/lib/WAUSync/Protocols/index.d.ts.map +1 -0
  385. package/lib/WAUSync/Protocols/index.js +5 -20
  386. package/lib/WAUSync/Protocols/index.js.map +1 -0
  387. package/lib/WAUSync/USyncQuery.d.ts +5 -4
  388. package/lib/WAUSync/USyncQuery.d.ts.map +1 -0
  389. package/lib/WAUSync/USyncQuery.js +40 -35
  390. package/lib/WAUSync/USyncQuery.js.map +1 -0
  391. package/lib/WAUSync/USyncUser.d.ts +7 -4
  392. package/lib/WAUSync/USyncUser.d.ts.map +1 -0
  393. package/lib/WAUSync/USyncUser.js +2 -5
  394. package/lib/WAUSync/USyncUser.js.map +1 -0
  395. package/lib/WAUSync/index.d.ts +4 -3
  396. package/lib/WAUSync/index.d.ts.map +1 -0
  397. package/lib/WAUSync/index.js +4 -19
  398. package/lib/WAUSync/index.js.map +1 -0
  399. package/lib/index.d.ts +13 -0
  400. package/lib/index.d.ts.map +1 -0
  401. package/lib/index.js +16 -31
  402. package/lib/index.js.map +1 -0
  403. package/package.json +34 -74
  404. package/Readme.md +0 -1
  405. package/WASignalGroup/GroupProtocol.js +0 -1697
  406. package/WASignalGroup/ciphertext_message.js +0 -16
  407. package/WASignalGroup/group_cipher.js +0 -120
  408. package/WASignalGroup/group_session_builder.js +0 -46
  409. package/WASignalGroup/index.js +0 -5
  410. package/WASignalGroup/keyhelper.js +0 -21
  411. package/WASignalGroup/protobufs.js +0 -3
  412. package/WASignalGroup/queue_job.js +0 -69
  413. package/WASignalGroup/sender_chain_key.js +0 -50
  414. package/WASignalGroup/sender_key_distribution_message.js +0 -78
  415. package/WASignalGroup/sender_key_message.js +0 -92
  416. package/WASignalGroup/sender_key_name.js +0 -70
  417. package/WASignalGroup/sender_key_record.js +0 -56
  418. package/WASignalGroup/sender_key_state.js +0 -129
  419. package/lib/Defaults/baileys-version.json +0 -3
  420. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  421. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  422. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  423. package/lib/Socket/Client/web-socket-client.js +0 -62
  424. package/lib/Socket/registration.d.ts +0 -264
  425. package/lib/Socket/registration.js +0 -166
  426. package/lib/Socket/usync.d.ts +0 -37
  427. package/lib/Socket/usync.js +0 -70
  428. package/lib/Store/index.d.ts +0 -3
  429. package/lib/Store/index.js +0 -10
  430. package/lib/Store/make-cache-manager-store.d.ts +0 -14
  431. package/lib/Store/make-cache-manager-store.js +0 -83
  432. package/lib/Store/make-in-memory-store.d.ts +0 -118
  433. package/lib/Store/make-in-memory-store.js +0 -431
  434. package/lib/Store/make-ordered-dictionary.d.ts +0 -13
  435. package/lib/Store/make-ordered-dictionary.js +0 -81
  436. package/lib/Store/object-repository.d.ts +0 -10
  437. package/lib/Store/object-repository.js +0 -27
  438. package/lib/Utils/baileys-event-stream.d.ts +0 -16
  439. package/lib/Utils/baileys-event-stream.js +0 -63
  440. package/lib/Utils/use-single-file-auth-state.d.ts +0 -12
  441. package/lib/Utils/use-single-file-auth-state.js +0 -75
@@ -1,157 +1,326 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.makeMessagesRecvSocket = void 0;
7
- const boom_1 = require("@hapi/boom");
8
- const crypto_1 = require("crypto");
9
- const node_cache_1 = __importDefault(require("node-cache"));
10
- const WAProto_1 = require("../../WAProto");
11
- const Defaults_1 = require("../Defaults");
12
- const Types_1 = require("../Types");
13
- const Utils_1 = require("../Utils");
14
- const make_mutex_1 = require("../Utils/make-mutex");
15
- const WABinary_1 = require("../WABinary");
16
- const groups_1 = require("./groups");
17
- const messages_send_1 = require("./messages-send");
18
- const makeMessagesRecvSocket = (config) => {
19
- const { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid } = config;
20
- const sock = (0, messages_send_1.makeMessagesSocket)(config);
21
- const { ev, authState, ws, processingMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, getUSyncDevices, sendPeerDataOperationMessage, createParticipantNodes } = sock;
1
+ import NodeCache from '@cacheable/node-cache';
2
+ import { Boom } from '@hapi/boom';
3
+ import { randomBytes } from 'crypto';
4
+ import Long from 'long';
5
+ import { proto } from '../../WAProto/index.js';
6
+ import { DEFAULT_CACHE_TTLS, KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT, PLACEHOLDER_MAX_AGE_SECONDS, STATUS_EXPIRY_SECONDS } from '../Defaults/index.js';
7
+ import { WAMessageStatus, WAMessageStubType } from '../Types/index.js';
8
+ import { aesDecryptCTR, aesEncryptGCM, cleanMessage, Curve, decodeMediaRetryNode, decodeMessageNode, decryptMessageNode, delay, derivePairingCodeKey, encodeBigEndian, encodeSignedDeviceIdentity, extractAddressingContext, getCallStatusFromNode, getHistoryMsg, getNextPreKeys, getStatusFromReceiptType, handleIdentityChange, hkdf, MISSING_KEYS_ERROR_TEXT, NACK_REASONS, NO_MESSAGE_FOUND_ERROR_TEXT, toNumber, unixTimestampSeconds, xmppPreKey, xmppSignedPreKey } from '../Utils/index.js';
9
+ import { makeMutex } from '../Utils/make-mutex.js';
10
+ import { makeOfflineNodeProcessor } from '../Utils/offline-node-processor.js';
11
+ import { buildAckStanza } from '../Utils/stanza-ack.js';
12
+ import { areJidsSameUser, binaryNodeToString, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildren, getBinaryNodeChildString, isJidGroup, isJidNewsletter, isJidStatusBroadcast, isLidUser, isPnUser, jidDecode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
13
+ import { extractGroupMetadata } from './groups.js';
14
+ import { makeMessagesSocket } from './messages-send.js';
15
+ export const makeMessagesRecvSocket = (config) => {
16
+ const { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid, enableAutoSessionRecreation } = config;
17
+ const sock = makeMessagesSocket(config);
18
+ const { ev, authState, ws, messageMutex, notificationMutex, receiptMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage, messageRetryManager } = sock;
22
19
  /** this mutex ensures that each retryRequest will wait for the previous one to finish */
23
- const retryMutex = (0, make_mutex_1.makeMutex)();
24
- const msgRetryCache = config.msgRetryCounterCache || new node_cache_1.default({
25
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
26
- useClones: false
27
- });
28
- const callOfferCache = config.callOfferCache || new node_cache_1.default({
29
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.CALL_OFFER, // 5 mins
30
- useClones: false
31
- });
32
- const placeholderResendCache = config.placeholderResendCache || new node_cache_1.default({
33
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
34
- useClones: false
35
- });
20
+ const retryMutex = makeMutex();
21
+ const msgRetryCache = config.msgRetryCounterCache ||
22
+ new NodeCache({
23
+ stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
24
+ useClones: false
25
+ });
26
+ const callOfferCache = config.callOfferCache ||
27
+ new NodeCache({
28
+ stdTTL: DEFAULT_CACHE_TTLS.CALL_OFFER, // 5 mins
29
+ useClones: false
30
+ });
31
+ const placeholderResendCache = config.placeholderResendCache ||
32
+ new NodeCache({
33
+ stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
34
+ useClones: false
35
+ });
36
+ // Debounce identity-change session refreshes per JID to avoid bursts
37
+ const identityAssertDebounce = new NodeCache({ stdTTL: 5, useClones: false });
36
38
  let sendActiveReceipts = false;
37
- const sendMessageAck = async ({ tag, attrs, content }, errorCode) => {
38
- const stanza = {
39
- tag: 'ack',
40
- attrs: {
41
- id: attrs.id,
42
- to: attrs.from,
43
- class: tag
44
- }
45
- };
46
- if (!!errorCode) {
47
- stanza.attrs.error = errorCode.toString();
39
+ const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
40
+ if (!authState.creds.me?.id) {
41
+ throw new Boom('Not authenticated');
48
42
  }
49
- if (!!attrs.participant) {
50
- stanza.attrs.participant = attrs.participant;
43
+ const pdoMessage = {
44
+ historySyncOnDemandRequest: {
45
+ chatJid: oldestMsgKey.remoteJid,
46
+ oldestMsgFromMe: oldestMsgKey.fromMe,
47
+ oldestMsgId: oldestMsgKey.id,
48
+ oldestMsgTimestampMs: oldestMsgTimestamp,
49
+ onDemandMsgCount: count
50
+ },
51
+ peerDataOperationRequestType: proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
52
+ };
53
+ return sendPeerDataOperationMessage(pdoMessage);
54
+ };
55
+ const requestPlaceholderResend = async (messageKey, msgData) => {
56
+ if (!authState.creds.me?.id) {
57
+ throw new Boom('Not authenticated');
51
58
  }
52
- if (!!attrs.recipient) {
53
- stanza.attrs.recipient = attrs.recipient;
59
+ if (await placeholderResendCache.get(messageKey?.id)) {
60
+ logger.debug({ messageKey }, 'already requested resend');
61
+ return;
54
62
  }
55
- if (!!attrs.type && (tag !== 'message' || (0, WABinary_1.getBinaryNodeChild)({ tag, attrs, content }, 'unavailable') || errorCode !== 0)) {
56
- stanza.attrs.type = attrs.type;
63
+ else {
64
+ // Store original message data so PDO response handler can preserve
65
+ // metadata (LID details, timestamps, etc.) that the phone may omit
66
+ await placeholderResendCache.set(messageKey?.id, msgData || true);
57
67
  }
58
- if (tag === 'message' && (0, WABinary_1.getBinaryNodeChild)({ tag, attrs, content }, 'unavailable')) {
59
- stanza.attrs.from = authState.creds.me.id;
68
+ await delay(2000);
69
+ if (!(await placeholderResendCache.get(messageKey?.id))) {
70
+ logger.debug({ messageKey }, 'message received while resend requested');
71
+ return 'RESOLVED';
60
72
  }
61
- logger.debug({ recv: { tag, attrs }, sent: stanza.attrs }, 'sent ack');
62
- await sendNode(stanza);
73
+ const pdoMessage = {
74
+ placeholderMessageResendRequest: [
75
+ {
76
+ messageKey
77
+ }
78
+ ],
79
+ peerDataOperationRequestType: proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
80
+ };
81
+ setTimeout(async () => {
82
+ if (await placeholderResendCache.get(messageKey?.id)) {
83
+ logger.debug({ messageKey }, 'PDO message without response after 8 seconds. Phone possibly offline');
84
+ await placeholderResendCache.del(messageKey?.id);
85
+ }
86
+ }, 8000);
87
+ return sendPeerDataOperationMessage(pdoMessage);
63
88
  };
64
- const offerCall = async (toJid, isVideo = false) => {
65
- const callId = (0, crypto_1.randomBytes)(16).toString('hex').toUpperCase().substring(0, 64);
66
- const offerContent = [];
67
- offerContent.push({ tag: 'audio', attrs: { enc: 'opus', rate: '16000' }, content: undefined });
68
- offerContent.push({ tag: 'audio', attrs: { enc: 'opus', rate: '8000' }, content: undefined });
69
- if (isVideo) {
70
- offerContent.push({
71
- tag: 'video',
72
- attrs: { enc: 'vp8', dec: 'vp8', orientation: '0', 'screen_width': '1920', 'screen_height': '1080', 'device_orientation': '0' },
73
- content: undefined
74
- });
89
+ // Handles mex newsletter notifications
90
+ const handleMexNewsletterNotification = async (node) => {
91
+ const mexNode = getBinaryNodeChild(node, 'mex');
92
+ if (!mexNode?.content) {
93
+ logger.warn({ node }, 'Invalid mex newsletter notification');
94
+ return;
75
95
  }
76
- offerContent.push({ tag: 'net', attrs: { medium: '3' }, content: undefined });
77
- offerContent.push({ tag: 'capability', attrs: { ver: '1' }, content: new Uint8Array([1, 4, 255, 131, 207, 4]) });
78
- offerContent.push({ tag: 'encopt', attrs: { keygen: '2' }, content: undefined });
79
- const encKey = (0, crypto_1.randomBytes)(32);
80
- const devices = (await getUSyncDevices([toJid], true, false)).map(({ user, device }) => (0, WABinary_1.jidEncode)(user, 's.whatsapp.net', device));
81
- await assertSessions(devices, true);
82
- const { nodes: destinations, shouldIncludeDeviceIdentity } = await createParticipantNodes(devices, {
83
- call: {
84
- callKey: new Uint8Array(encKey)
85
- }
86
- }, { count: '0' });
87
- offerContent.push({ tag: 'destination', attrs: {}, content: destinations });
88
- if (shouldIncludeDeviceIdentity) {
89
- offerContent.push({
90
- tag: 'device-identity',
91
- attrs: {},
92
- content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
93
- });
96
+ let data;
97
+ try {
98
+ data = JSON.parse(mexNode.content.toString());
94
99
  }
95
- const stanza = ({
96
- tag: 'call',
97
- attrs: {
98
- id: await config.generateMessageIDV2() ?? (0, Utils_1.generateMessageIDV2)(),
99
- to: toJid,
100
- },
101
- content: [{
102
- tag: 'offer',
103
- attrs: {
104
- 'call-id': callId,
105
- 'call-creator': authState.creds.me.id,
106
- },
107
- content: offerContent,
108
- }],
109
- });
110
- await query(stanza);
111
- return {
112
- id: callId,
113
- to: toJid
114
- };
100
+ catch (error) {
101
+ logger.error({ err: error, node }, 'Failed to parse mex newsletter notification');
102
+ return;
103
+ }
104
+ const operation = data?.operation;
105
+ const updates = data?.updates;
106
+ if (!updates || !operation) {
107
+ logger.warn({ data }, 'Invalid mex newsletter notification content');
108
+ return;
109
+ }
110
+ logger.info({ operation, updates }, 'got mex newsletter notification');
111
+ switch (operation) {
112
+ case 'NotificationNewsletterUpdate':
113
+ for (const update of updates) {
114
+ if (update.jid && update.settings && Object.keys(update.settings).length > 0) {
115
+ ev.emit('newsletter-settings.update', {
116
+ id: update.jid,
117
+ update: update.settings
118
+ });
119
+ }
120
+ }
121
+ break;
122
+ case 'NotificationNewsletterAdminPromote':
123
+ for (const update of updates) {
124
+ if (update.jid && update.user) {
125
+ ev.emit('newsletter-participants.update', {
126
+ id: update.jid,
127
+ author: node.attrs.from,
128
+ user: update.user,
129
+ new_role: 'ADMIN',
130
+ action: 'promote'
131
+ });
132
+ }
133
+ }
134
+ break;
135
+ default:
136
+ logger.info({ operation, data }, 'Unhandled mex newsletter notification');
137
+ break;
138
+ }
139
+ };
140
+ // Handles newsletter notifications
141
+ const handleNewsletterNotification = async (node) => {
142
+ const from = node.attrs.from;
143
+ const child = getAllBinaryNodeChildren(node)[0];
144
+ const author = node.attrs.participant;
145
+ logger.info({ from, child }, 'got newsletter notification');
146
+ switch (child.tag) {
147
+ case 'reaction':
148
+ const reactionUpdate = {
149
+ id: from,
150
+ server_id: child.attrs.message_id,
151
+ reaction: {
152
+ code: getBinaryNodeChildString(child, 'reaction'),
153
+ count: 1
154
+ }
155
+ };
156
+ ev.emit('newsletter.reaction', reactionUpdate);
157
+ break;
158
+ case 'view':
159
+ const viewUpdate = {
160
+ id: from,
161
+ server_id: child.attrs.message_id,
162
+ count: parseInt(child.content?.toString() || '0', 10)
163
+ };
164
+ ev.emit('newsletter.view', viewUpdate);
165
+ break;
166
+ case 'participant':
167
+ const participantUpdate = {
168
+ id: from,
169
+ author,
170
+ user: child.attrs.jid,
171
+ action: child.attrs.action,
172
+ new_role: child.attrs.role
173
+ };
174
+ ev.emit('newsletter-participants.update', participantUpdate);
175
+ break;
176
+ case 'update':
177
+ const settingsNode = getBinaryNodeChild(child, 'settings');
178
+ if (settingsNode) {
179
+ const update = {};
180
+ const nameNode = getBinaryNodeChild(settingsNode, 'name');
181
+ if (nameNode?.content)
182
+ update.name = nameNode.content.toString();
183
+ const descriptionNode = getBinaryNodeChild(settingsNode, 'description');
184
+ if (descriptionNode?.content)
185
+ update.description = descriptionNode.content.toString();
186
+ ev.emit('newsletter-settings.update', {
187
+ id: from,
188
+ update
189
+ });
190
+ }
191
+ break;
192
+ case 'message':
193
+ const plaintextNode = getBinaryNodeChild(child, 'plaintext');
194
+ if (plaintextNode?.content) {
195
+ try {
196
+ const contentBuf = typeof plaintextNode.content === 'string'
197
+ ? Buffer.from(plaintextNode.content, 'binary')
198
+ : Buffer.from(plaintextNode.content);
199
+ const messageProto = proto.Message.decode(contentBuf).toJSON();
200
+ const fullMessage = proto.WebMessageInfo.fromObject({
201
+ key: {
202
+ remoteJid: from,
203
+ id: child.attrs.message_id || child.attrs.server_id,
204
+ fromMe: false // TODO: is this really true though
205
+ },
206
+ message: messageProto,
207
+ messageTimestamp: +child.attrs.t
208
+ }).toJSON();
209
+ await upsertMessage(fullMessage, 'append');
210
+ logger.info('Processed plaintext newsletter message');
211
+ }
212
+ catch (error) {
213
+ logger.error({ error }, 'Failed to decode plaintext newsletter message');
214
+ }
215
+ }
216
+ break;
217
+ default:
218
+ logger.warn({ node }, 'Unknown newsletter notification');
219
+ break;
220
+ }
221
+ };
222
+ const sendMessageAck = async (node, errorCode) => {
223
+ const stanza = buildAckStanza(node, errorCode, authState.creds.me.id);
224
+ logger.debug({ recv: { tag: node.tag, attrs: node.attrs }, sent: stanza.attrs }, 'sent ack');
225
+ await sendNode(stanza);
115
226
  };
116
227
  const rejectCall = async (callId, callFrom) => {
117
- const stanza = ({
228
+ const stanza = {
118
229
  tag: 'call',
119
230
  attrs: {
120
231
  from: authState.creds.me.id,
121
- to: callFrom,
232
+ to: callFrom
122
233
  },
123
- content: [{
234
+ content: [
235
+ {
124
236
  tag: 'reject',
125
237
  attrs: {
126
238
  'call-id': callId,
127
239
  'call-creator': callFrom,
128
- count: '0',
240
+ count: '0'
129
241
  },
130
- content: undefined,
131
- }],
132
- });
242
+ content: undefined
243
+ }
244
+ ]
245
+ };
133
246
  await query(stanza);
134
247
  };
135
248
  const sendRetryRequest = async (node, forceIncludeKeys = false) => {
136
- const { fullMessage } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '');
249
+ const { fullMessage } = decodeMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '');
137
250
  const { key: msgKey } = fullMessage;
138
251
  const msgId = msgKey.id;
139
- const key = `${msgId}:${msgKey === null || msgKey === void 0 ? void 0 : msgKey.participant}`;
140
- let retryCount = msgRetryCache.get(key) || 0;
141
- if (retryCount >= maxMsgRetryCount) {
142
- logger.debug({ retryCount, msgId }, 'reached retry limit, clearing');
143
- msgRetryCache.del(key);
144
- return;
252
+ if (messageRetryManager) {
253
+ // Check if we've exceeded max retries using the new system
254
+ if (messageRetryManager.hasExceededMaxRetries(msgId)) {
255
+ logger.debug({ msgId }, 'reached retry limit with new retry manager, clearing');
256
+ messageRetryManager.markRetryFailed(msgId);
257
+ return;
258
+ }
259
+ // Increment retry count using new system
260
+ const retryCount = messageRetryManager.incrementRetryCount(msgId);
261
+ // Use the new retry count for the rest of the logic
262
+ const key = `${msgId}:${msgKey?.participant}`;
263
+ await msgRetryCache.set(key, retryCount);
264
+ }
265
+ else {
266
+ // Fallback to old system
267
+ const key = `${msgId}:${msgKey?.participant}`;
268
+ let retryCount = (await msgRetryCache.get(key)) || 0;
269
+ if (retryCount >= maxMsgRetryCount) {
270
+ logger.debug({ retryCount, msgId }, 'reached retry limit, clearing');
271
+ await msgRetryCache.del(key);
272
+ return;
273
+ }
274
+ retryCount += 1;
275
+ await msgRetryCache.set(key, retryCount);
145
276
  }
146
- retryCount += 1;
147
- msgRetryCache.set(key, retryCount);
277
+ const key = `${msgId}:${msgKey?.participant}`;
278
+ const retryCount = (await msgRetryCache.get(key)) || 1;
148
279
  const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds;
149
- if (retryCount === 1) {
150
- //request a resend via phone
151
- const msgId = await requestPlaceholderResend(msgKey);
152
- logger.debug(`sendRetryRequest: requested placeholder resend for message ${msgId}`);
280
+ const fromJid = node.attrs.from;
281
+ // Check if we should recreate the session
282
+ let shouldRecreateSession = false;
283
+ let recreateReason = '';
284
+ if (enableAutoSessionRecreation && messageRetryManager && retryCount > 1) {
285
+ try {
286
+ // Check if we have a session with this JID
287
+ const sessionId = signalRepository.jidToSignalProtocolAddress(fromJid);
288
+ const hasSession = await signalRepository.validateSession(fromJid);
289
+ const result = messageRetryManager.shouldRecreateSession(fromJid, hasSession.exists);
290
+ shouldRecreateSession = result.recreate;
291
+ recreateReason = result.reason;
292
+ if (shouldRecreateSession) {
293
+ logger.debug({ fromJid, retryCount, reason: recreateReason }, 'recreating session for retry');
294
+ // Delete existing session to force recreation
295
+ await authState.keys.set({ session: { [sessionId]: null } });
296
+ forceIncludeKeys = true;
297
+ }
298
+ }
299
+ catch (error) {
300
+ logger.warn({ error, fromJid }, 'failed to check session recreation');
301
+ }
302
+ }
303
+ if (retryCount <= 2) {
304
+ // Use new retry manager for phone requests if available
305
+ if (messageRetryManager) {
306
+ // Schedule phone request with delay (like whatsmeow)
307
+ messageRetryManager.schedulePhoneRequest(msgId, async () => {
308
+ try {
309
+ const requestId = await requestPlaceholderResend(msgKey);
310
+ logger.debug(`sendRetryRequest: requested placeholder resend (${requestId}) for message ${msgId} (scheduled)`);
311
+ }
312
+ catch (error) {
313
+ logger.warn({ error, msgId }, 'failed to send scheduled phone request');
314
+ }
315
+ });
316
+ }
317
+ else {
318
+ // Fallback to immediate request
319
+ const msgId = await requestPlaceholderResend(msgKey);
320
+ logger.debug(`sendRetryRequest: requested placeholder resend for message ${msgId}`);
321
+ }
153
322
  }
154
- const deviceIdentity = (0, Utils_1.encodeSignedDeviceIdentity)(account, true);
323
+ const deviceIdentity = encodeSignedDeviceIdentity(account, true);
155
324
  await authState.keys.transaction(async () => {
156
325
  const receipt = {
157
326
  tag: 'receipt',
@@ -167,13 +336,15 @@ const makeMessagesRecvSocket = (config) => {
167
336
  count: retryCount.toString(),
168
337
  id: node.attrs.id,
169
338
  t: node.attrs.t,
170
- v: '1'
339
+ v: '1',
340
+ // ADD ERROR FIELD
341
+ error: '0'
171
342
  }
172
343
  },
173
344
  {
174
345
  tag: 'registration',
175
346
  attrs: {},
176
- content: (0, Utils_1.encodeBigEndian)(authState.creds.registrationId)
347
+ content: encodeBigEndian(authState.creds.registrationId)
177
348
  }
178
349
  ]
179
350
  };
@@ -183,8 +354,8 @@ const makeMessagesRecvSocket = (config) => {
183
354
  if (node.attrs.participant) {
184
355
  receipt.attrs.participant = node.attrs.participant;
185
356
  }
186
- if (retryCount > 1 || forceIncludeKeys) {
187
- const { update, preKeys } = await (0, Utils_1.getNextPreKeys)(authState, 1);
357
+ if (retryCount > 1 || forceIncludeKeys || shouldRecreateSession) {
358
+ const { update, preKeys } = await getNextPreKeys(authState, 1);
188
359
  const [keyId] = Object.keys(preKeys);
189
360
  const key = preKeys[+keyId];
190
361
  const content = receipt.content;
@@ -192,10 +363,10 @@ const makeMessagesRecvSocket = (config) => {
192
363
  tag: 'keys',
193
364
  attrs: {},
194
365
  content: [
195
- { tag: 'type', attrs: {}, content: Buffer.from(Defaults_1.KEY_BUNDLE_TYPE) },
366
+ { tag: 'type', attrs: {}, content: Buffer.from(KEY_BUNDLE_TYPE) },
196
367
  { tag: 'identity', attrs: {}, content: identityKey.public },
197
- (0, Utils_1.xmppPreKey)(key, +keyId),
198
- (0, Utils_1.xmppSignedPreKey)(signedPreKey),
368
+ xmppPreKey(key, +keyId),
369
+ xmppSignedPreKey(signedPreKey),
199
370
  { tag: 'device-identity', attrs: {}, content: deviceIdentity }
200
371
  ]
201
372
  });
@@ -203,63 +374,73 @@ const makeMessagesRecvSocket = (config) => {
203
374
  }
204
375
  await sendNode(receipt);
205
376
  logger.info({ msgAttrs: node.attrs, retryCount }, 'sent retry receipt');
206
- });
377
+ }, authState?.creds?.me?.id || 'sendRetryRequest');
207
378
  };
208
379
  const handleEncryptNotification = async (node) => {
209
380
  const from = node.attrs.from;
210
- if (from === WABinary_1.S_WHATSAPP_NET) {
211
- const countChild = (0, WABinary_1.getBinaryNodeChild)(node, 'count');
381
+ if (from === S_WHATSAPP_NET) {
382
+ const countChild = getBinaryNodeChild(node, 'count');
212
383
  const count = +countChild.attrs.value;
213
- const shouldUploadMorePreKeys = count < Defaults_1.MIN_PREKEY_COUNT;
384
+ const shouldUploadMorePreKeys = count < MIN_PREKEY_COUNT;
214
385
  logger.debug({ count, shouldUploadMorePreKeys }, 'recv pre-key count');
215
386
  if (shouldUploadMorePreKeys) {
216
387
  await uploadPreKeys();
217
388
  }
218
389
  }
219
390
  else {
220
- const identityNode = (0, WABinary_1.getBinaryNodeChild)(node, 'identity');
221
- if (identityNode) {
222
- logger.info({ jid: from }, 'identity changed');
223
- // not handling right now
224
- // signal will override new identity anyway
225
- }
226
- else {
391
+ const result = await handleIdentityChange(node, {
392
+ meId: authState.creds.me?.id,
393
+ meLid: authState.creds.me?.lid,
394
+ validateSession: signalRepository.validateSession,
395
+ assertSessions,
396
+ debounceCache: identityAssertDebounce,
397
+ logger
398
+ });
399
+ if (result.action === 'no_identity_node') {
227
400
  logger.info({ node }, 'unknown encrypt notification');
228
401
  }
229
402
  }
230
403
  };
231
- const handleGroupNotification = (participant, child, msg) => {
232
- var _a, _b, _c, _d;
233
- const participantJid = ((_b = (_a = (0, WABinary_1.getBinaryNodeChild)(child, 'participant')) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b.jid) || participant;
234
- switch (child === null || child === void 0 ? void 0 : child.tag) {
404
+ const handleGroupNotification = (fullNode, child, msg) => {
405
+ // TODO: Support PN/LID (Here is only LID now)
406
+ const actingParticipantLid = fullNode.attrs.participant;
407
+ const actingParticipantPn = fullNode.attrs.participant_pn;
408
+ const affectedParticipantLid = getBinaryNodeChild(child, 'participant')?.attrs?.jid || actingParticipantLid;
409
+ const affectedParticipantPn = getBinaryNodeChild(child, 'participant')?.attrs?.phone_number || actingParticipantPn;
410
+ switch (child?.tag) {
235
411
  case 'create':
236
- const metadata = (0, groups_1.extractGroupMetadata)(child);
237
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_CREATE;
412
+ const metadata = extractGroupMetadata(child);
413
+ msg.messageStubType = WAMessageStubType.GROUP_CREATE;
238
414
  msg.messageStubParameters = [metadata.subject];
239
- msg.key = { participant: metadata.owner };
240
- ev.emit('chats.upsert', [{
415
+ msg.key = { participant: metadata.owner, participantAlt: metadata.ownerPn };
416
+ ev.emit('chats.upsert', [
417
+ {
241
418
  id: metadata.id,
242
419
  name: metadata.subject,
243
- conversationTimestamp: metadata.creation,
244
- }]);
245
- ev.emit('groups.upsert', [{
420
+ conversationTimestamp: metadata.creation
421
+ }
422
+ ]);
423
+ ev.emit('groups.upsert', [
424
+ {
246
425
  ...metadata,
247
- author: participant
248
- }]);
426
+ author: actingParticipantLid,
427
+ authorPn: actingParticipantPn
428
+ }
429
+ ]);
249
430
  break;
250
431
  case 'ephemeral':
251
432
  case 'not_ephemeral':
252
433
  msg.message = {
253
434
  protocolMessage: {
254
- type: WAProto_1.proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
435
+ type: proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
255
436
  ephemeralExpiration: +(child.attrs.expiration || 0)
256
437
  }
257
438
  };
258
439
  break;
259
440
  case 'modify':
260
- const oldNumber = (0, WABinary_1.getBinaryNodeChildren)(child, 'participant').map(p => p.attrs.jid);
441
+ const oldNumber = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid);
261
442
  msg.messageStubParameters = oldNumber || [];
262
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
443
+ msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
263
444
  break;
264
445
  case 'promote':
265
446
  case 'demote':
@@ -267,126 +448,141 @@ const makeMessagesRecvSocket = (config) => {
267
448
  case 'add':
268
449
  case 'leave':
269
450
  const stubType = `GROUP_PARTICIPANT_${child.tag.toUpperCase()}`;
270
- msg.messageStubType = Types_1.WAMessageStubType[stubType];
271
- const participants = (0, WABinary_1.getBinaryNodeChildren)(child, 'participant').map(p => p.attrs.jid);
451
+ msg.messageStubType = WAMessageStubType[stubType];
452
+ const participants = getBinaryNodeChildren(child, 'participant').map(({ attrs }) => {
453
+ // TODO: Store LID MAPPINGS
454
+ return {
455
+ id: attrs.jid,
456
+ phoneNumber: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined,
457
+ lid: isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined,
458
+ admin: (attrs.type || null)
459
+ };
460
+ });
272
461
  if (participants.length === 1 &&
273
462
  // if recv. "remove" message and sender removed themselves
274
463
  // mark as left
275
- (0, WABinary_1.areJidsSameUser)(participants[0], participant) &&
464
+ (areJidsSameUser(participants[0].id, actingParticipantLid) ||
465
+ areJidsSameUser(participants[0].id, actingParticipantPn)) &&
276
466
  child.tag === 'remove') {
277
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_PARTICIPANT_LEAVE;
467
+ msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_LEAVE;
278
468
  }
279
- msg.messageStubParameters = participants;
469
+ msg.messageStubParameters = participants.map(a => JSON.stringify(a));
280
470
  break;
281
471
  case 'subject':
282
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_SUBJECT;
472
+ msg.messageStubType = WAMessageStubType.GROUP_CHANGE_SUBJECT;
283
473
  msg.messageStubParameters = [child.attrs.subject];
284
474
  break;
285
475
  case 'description':
286
- const description = (_d = (_c = (0, WABinary_1.getBinaryNodeChild)(child, 'body')) === null || _c === void 0 ? void 0 : _c.content) === null || _d === void 0 ? void 0 : _d.toString();
287
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_DESCRIPTION;
476
+ const description = getBinaryNodeChild(child, 'body')?.content?.toString();
477
+ msg.messageStubType = WAMessageStubType.GROUP_CHANGE_DESCRIPTION;
288
478
  msg.messageStubParameters = description ? [description] : undefined;
289
479
  break;
290
480
  case 'announcement':
291
481
  case 'not_announcement':
292
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
293
- msg.messageStubParameters = [(child.tag === 'announcement') ? 'on' : 'off'];
482
+ msg.messageStubType = WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
483
+ msg.messageStubParameters = [child.tag === 'announcement' ? 'on' : 'off'];
294
484
  break;
295
485
  case 'locked':
296
486
  case 'unlocked':
297
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_RESTRICT;
298
- msg.messageStubParameters = [(child.tag === 'locked') ? 'on' : 'off'];
487
+ msg.messageStubType = WAMessageStubType.GROUP_CHANGE_RESTRICT;
488
+ msg.messageStubParameters = [child.tag === 'locked' ? 'on' : 'off'];
299
489
  break;
300
490
  case 'invite':
301
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_INVITE_LINK;
491
+ msg.messageStubType = WAMessageStubType.GROUP_CHANGE_INVITE_LINK;
302
492
  msg.messageStubParameters = [child.attrs.code];
303
493
  break;
304
494
  case 'member_add_mode':
305
495
  const addMode = child.content;
306
496
  if (addMode) {
307
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBER_ADD_MODE;
497
+ msg.messageStubType = WAMessageStubType.GROUP_MEMBER_ADD_MODE;
308
498
  msg.messageStubParameters = [addMode.toString()];
309
499
  }
310
500
  break;
311
501
  case 'membership_approval_mode':
312
- const approvalMode = (0, WABinary_1.getBinaryNodeChild)(child, 'group_join');
502
+ const approvalMode = getBinaryNodeChild(child, 'group_join');
313
503
  if (approvalMode) {
314
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE;
504
+ msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE;
315
505
  msg.messageStubParameters = [approvalMode.attrs.state];
316
506
  }
317
507
  break;
318
508
  case 'created_membership_requests':
319
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
320
- msg.messageStubParameters = [participantJid, 'created', child.attrs.request_method];
509
+ msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
510
+ msg.messageStubParameters = [
511
+ JSON.stringify({ lid: affectedParticipantLid, pn: affectedParticipantPn }),
512
+ 'created',
513
+ child.attrs.request_method
514
+ ];
321
515
  break;
322
516
  case 'revoked_membership_requests':
323
- const isDenied = (0, WABinary_1.areJidsSameUser)(participantJid, participant);
324
- msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
325
- msg.messageStubParameters = [participantJid, isDenied ? 'revoked' : 'rejected'];
517
+ const isDenied = areJidsSameUser(affectedParticipantLid, actingParticipantLid);
518
+ // TODO: LIDMAPPING SUPPORT
519
+ msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
520
+ msg.messageStubParameters = [
521
+ JSON.stringify({ lid: affectedParticipantLid, pn: affectedParticipantPn }),
522
+ isDenied ? 'revoked' : 'rejected'
523
+ ];
326
524
  break;
327
525
  }
328
526
  };
329
527
  const processNotification = async (node) => {
330
- var _a, _b, _c;
331
528
  const result = {};
332
- const [child] = (0, WABinary_1.getAllBinaryNodeChildren)(node);
529
+ const [child] = getAllBinaryNodeChildren(node);
333
530
  const nodeType = node.attrs.type;
334
- const from = (0, WABinary_1.jidNormalizedUser)(node.attrs.from);
531
+ const from = jidNormalizedUser(node.attrs.from);
335
532
  switch (nodeType) {
336
- case 'privacy_token':
337
- const tokenList = (0, WABinary_1.getBinaryNodeChildren)(child, 'token');
338
- for (const { attrs, content } of tokenList) {
339
- const jid = attrs.jid;
340
- ev.emit('chats.update', [
341
- {
342
- id: jid,
343
- tcToken: content
344
- }
345
- ]);
346
- logger.debug({ jid }, 'got privacy token update');
347
- }
533
+ case 'newsletter':
534
+ await handleNewsletterNotification(node);
535
+ break;
536
+ case 'mex':
537
+ await handleMexNewsletterNotification(node);
348
538
  break;
349
539
  case 'w:gp2':
350
- handleGroupNotification(node.attrs.participant, child, result);
540
+ // TODO: HANDLE PARTICIPANT_PN
541
+ handleGroupNotification(node, child, result);
351
542
  break;
352
543
  case 'mediaretry':
353
- const event = (0, Utils_1.decodeMediaRetryNode)(node);
544
+ const event = decodeMediaRetryNode(node);
354
545
  ev.emit('messages.media-update', [event]);
355
546
  break;
356
547
  case 'encrypt':
357
548
  await handleEncryptNotification(node);
358
549
  break;
359
550
  case 'devices':
360
- const devices = (0, WABinary_1.getBinaryNodeChildren)(child, 'device');
361
- if ((0, WABinary_1.areJidsSameUser)(child.attrs.jid, authState.creds.me.id)) {
362
- const deviceJids = devices.map(d => d.attrs.jid);
363
- logger.info({ deviceJids }, 'got my own devices');
551
+ const devices = getBinaryNodeChildren(child, 'device');
552
+ if (areJidsSameUser(child.attrs.jid, authState.creds.me.id) ||
553
+ areJidsSameUser(child.attrs.lid, authState.creds.me.lid)) {
554
+ const deviceData = devices.map(d => ({ id: d.attrs.jid, lid: d.attrs.lid }));
555
+ logger.info({ deviceData }, 'my own devices changed');
364
556
  }
557
+ //TODO: drop a new event, add hashes
365
558
  break;
366
559
  case 'server_sync':
367
- const update = (0, WABinary_1.getBinaryNodeChild)(node, 'collection');
560
+ const update = getBinaryNodeChild(node, 'collection');
368
561
  if (update) {
369
562
  const name = update.attrs.name;
370
563
  await resyncAppState([name], false);
371
564
  }
372
565
  break;
373
566
  case 'picture':
374
- const setPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'set');
375
- const delPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'delete');
376
- ev.emit('contacts.update', [{
377
- id: (0, WABinary_1.jidNormalizedUser)((_a = node === null || node === void 0 ? void 0 : node.attrs) === null || _a === void 0 ? void 0 : _a.from) || ((_c = (_b = (setPicture || delPicture)) === null || _b === void 0 ? void 0 : _b.attrs) === null || _c === void 0 ? void 0 : _c.hash) || '',
567
+ const setPicture = getBinaryNodeChild(node, 'set');
568
+ const delPicture = getBinaryNodeChild(node, 'delete');
569
+ // TODO: WAJIDHASH stuff proper support inhouse
570
+ ev.emit('contacts.update', [
571
+ {
572
+ id: jidNormalizedUser(node?.attrs?.from) || (setPicture || delPicture)?.attrs?.hash || '',
378
573
  imgUrl: setPicture ? 'changed' : 'removed'
379
- }]);
380
- if ((0, WABinary_1.isJidGroup)(from)) {
574
+ }
575
+ ]);
576
+ if (isJidGroup(from)) {
381
577
  const node = setPicture || delPicture;
382
- result.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_ICON;
578
+ result.messageStubType = WAMessageStubType.GROUP_CHANGE_ICON;
383
579
  if (setPicture) {
384
580
  result.messageStubParameters = [setPicture.attrs.id];
385
581
  }
386
- result.participant = node === null || node === void 0 ? void 0 : node.attrs.author;
582
+ result.participant = node?.attrs.author;
387
583
  result.key = {
388
- ...result.key || {},
389
- participant: setPicture === null || setPicture === void 0 ? void 0 : setPicture.attrs.author
584
+ ...(result.key || {}),
585
+ participant: setPicture?.attrs.author
390
586
  };
391
587
  }
392
588
  break;
@@ -400,44 +596,48 @@ const makeMessagesRecvSocket = (config) => {
400
596
  ...authState.creds.accountSettings,
401
597
  defaultDisappearingMode: {
402
598
  ephemeralExpiration: newDuration,
403
- ephemeralSettingTimestamp: timestamp,
404
- },
599
+ ephemeralSettingTimestamp: timestamp
600
+ }
405
601
  }
406
602
  });
407
603
  }
408
604
  else if (child.tag === 'blocklist') {
409
- const blocklists = (0, WABinary_1.getBinaryNodeChildren)(child, 'item');
605
+ const blocklists = getBinaryNodeChildren(child, 'item');
410
606
  for (const { attrs } of blocklists) {
411
607
  const blocklist = [attrs.jid];
412
- const type = (attrs.action === 'block') ? 'add' : 'remove';
608
+ const type = attrs.action === 'block' ? 'add' : 'remove';
413
609
  ev.emit('blocklist.update', { blocklist, type });
414
610
  }
415
611
  }
416
612
  break;
417
613
  case 'link_code_companion_reg':
418
- const linkCodeCompanionReg = (0, WABinary_1.getBinaryNodeChild)(node, 'link_code_companion_reg');
419
- const ref = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'link_code_pairing_ref'));
420
- const primaryIdentityPublicKey = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'primary_identity_pub'));
421
- const primaryEphemeralPublicKeyWrapped = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'link_code_pairing_wrapped_primary_ephemeral_pub'));
614
+ const linkCodeCompanionReg = getBinaryNodeChild(node, 'link_code_companion_reg');
615
+ const ref = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_ref'));
616
+ const primaryIdentityPublicKey = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'primary_identity_pub'));
617
+ const primaryEphemeralPublicKeyWrapped = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_wrapped_primary_ephemeral_pub'));
422
618
  const codePairingPublicKey = await decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
423
- const companionSharedKey = Utils_1.Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey);
424
- const random = (0, crypto_1.randomBytes)(32);
425
- const linkCodeSalt = (0, crypto_1.randomBytes)(32);
426
- const linkCodePairingExpanded = await (0, Utils_1.hkdf)(companionSharedKey, 32, {
619
+ const companionSharedKey = Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey);
620
+ const random = randomBytes(32);
621
+ const linkCodeSalt = randomBytes(32);
622
+ const linkCodePairingExpanded = hkdf(companionSharedKey, 32, {
427
623
  salt: linkCodeSalt,
428
624
  info: 'link_code_pairing_key_bundle_encryption_key'
429
625
  });
430
- const encryptPayload = Buffer.concat([Buffer.from(authState.creds.signedIdentityKey.public), primaryIdentityPublicKey, random]);
431
- const encryptIv = (0, crypto_1.randomBytes)(12);
432
- const encrypted = (0, Utils_1.aesEncryptGCM)(encryptPayload, linkCodePairingExpanded, encryptIv, Buffer.alloc(0));
626
+ const encryptPayload = Buffer.concat([
627
+ Buffer.from(authState.creds.signedIdentityKey.public),
628
+ primaryIdentityPublicKey,
629
+ random
630
+ ]);
631
+ const encryptIv = randomBytes(12);
632
+ const encrypted = aesEncryptGCM(encryptPayload, linkCodePairingExpanded, encryptIv, Buffer.alloc(0));
433
633
  const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted]);
434
- const identitySharedKey = Utils_1.Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey);
634
+ const identitySharedKey = Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey);
435
635
  const identityPayload = Buffer.concat([companionSharedKey, identitySharedKey, random]);
436
- authState.creds.advSecretKey = (await (0, Utils_1.hkdf)(identityPayload, 32, { info: 'adv_secret' })).toString('base64');
636
+ authState.creds.advSecretKey = Buffer.from(hkdf(identityPayload, 32, { info: 'adv_secret' })).toString('base64');
437
637
  await query({
438
638
  tag: 'iq',
439
639
  attrs: {
440
- to: WABinary_1.S_WHATSAPP_NET,
640
+ to: S_WHATSAPP_NET,
441
641
  type: 'set',
442
642
  id: sock.generateMessageTag(),
443
643
  xmlns: 'md'
@@ -447,7 +647,7 @@ const makeMessagesRecvSocket = (config) => {
447
647
  tag: 'link_code_companion_reg',
448
648
  attrs: {
449
649
  jid: authState.creds.me.id,
450
- stage: 'companion_finish',
650
+ stage: 'companion_finish'
451
651
  },
452
652
  content: [
453
653
  {
@@ -471,52 +671,125 @@ const makeMessagesRecvSocket = (config) => {
471
671
  });
472
672
  authState.creds.registered = true;
473
673
  ev.emit('creds.update', authState.creds);
674
+ break;
675
+ case 'privacy_token':
676
+ await handlePrivacyTokenNotification(node);
677
+ break;
474
678
  }
475
679
  if (Object.keys(result).length) {
476
680
  return result;
477
681
  }
478
682
  };
683
+ const handlePrivacyTokenNotification = async (node) => {
684
+ const tokensNode = getBinaryNodeChild(node, 'tokens');
685
+ const from = jidNormalizedUser(node.attrs.from);
686
+ if (!tokensNode)
687
+ return;
688
+ const tokenNodes = getBinaryNodeChildren(tokensNode, 'token');
689
+ for (const tokenNode of tokenNodes) {
690
+ const { attrs, content } = tokenNode;
691
+ const type = attrs.type;
692
+ const timestamp = attrs.t;
693
+ if (type === 'trusted_contact' && content instanceof Buffer) {
694
+ logger.debug({
695
+ from,
696
+ timestamp,
697
+ tcToken: content
698
+ }, 'received trusted contact token');
699
+ await authState.keys.set({
700
+ tctoken: { [from]: { token: content, timestamp } }
701
+ });
702
+ }
703
+ }
704
+ };
479
705
  async function decipherLinkPublicKey(data) {
480
706
  const buffer = toRequiredBuffer(data);
481
707
  const salt = buffer.slice(0, 32);
482
- const secretKey = await (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
708
+ const secretKey = await derivePairingCodeKey(authState.creds.pairingCode, salt);
483
709
  const iv = buffer.slice(32, 48);
484
710
  const payload = buffer.slice(48, 80);
485
- return (0, Utils_1.aesDecryptCTR)(payload, secretKey, iv);
711
+ return aesDecryptCTR(payload, secretKey, iv);
486
712
  }
487
713
  function toRequiredBuffer(data) {
488
714
  if (data === undefined) {
489
- throw new boom_1.Boom('Invalid buffer', { statusCode: 400 });
715
+ throw new Boom('Invalid buffer', { statusCode: 400 });
490
716
  }
491
717
  return data instanceof Buffer ? data : Buffer.from(data);
492
718
  }
493
- const willSendMessageAgain = (id, participant) => {
719
+ const willSendMessageAgain = async (id, participant) => {
494
720
  const key = `${id}:${participant}`;
495
- const retryCount = msgRetryCache.get(key) || 0;
721
+ const retryCount = (await msgRetryCache.get(key)) || 0;
496
722
  return retryCount < maxMsgRetryCount;
497
723
  };
498
- const updateSendMessageAgainCount = (id, participant) => {
724
+ const updateSendMessageAgainCount = async (id, participant) => {
499
725
  const key = `${id}:${participant}`;
500
- const newValue = (msgRetryCache.get(key) || 0) + 1;
501
- msgRetryCache.set(key, newValue);
726
+ const newValue = ((await msgRetryCache.get(key)) || 0) + 1;
727
+ await msgRetryCache.set(key, newValue);
502
728
  };
503
729
  const sendMessagesAgain = async (key, ids, retryNode) => {
504
- var _a;
505
- const msgs = await Promise.all(ids.map(id => getMessage({ ...key, id })));
506
730
  const remoteJid = key.remoteJid;
507
731
  const participant = key.participant || remoteJid;
732
+ const retryCount = +retryNode.attrs.count || 1;
733
+ // Try to get messages from cache first, then fallback to getMessage
734
+ const msgs = [];
735
+ for (const id of ids) {
736
+ let msg;
737
+ // Try to get from retry cache first if enabled
738
+ if (messageRetryManager) {
739
+ const cachedMsg = messageRetryManager.getRecentMessage(remoteJid, id);
740
+ if (cachedMsg) {
741
+ msg = cachedMsg.message;
742
+ logger.debug({ jid: remoteJid, id }, 'found message in retry cache');
743
+ // Mark retry as successful since we found the message
744
+ messageRetryManager.markRetrySuccess(id);
745
+ }
746
+ }
747
+ // Fallback to getMessage if not found in cache
748
+ if (!msg) {
749
+ msg = await getMessage({ ...key, id });
750
+ if (msg) {
751
+ logger.debug({ jid: remoteJid, id }, 'found message via getMessage');
752
+ // Also mark as successful if found via getMessage
753
+ if (messageRetryManager) {
754
+ messageRetryManager.markRetrySuccess(id);
755
+ }
756
+ }
757
+ }
758
+ msgs.push(msg);
759
+ }
508
760
  // if it's the primary jid sending the request
509
761
  // just re-send the message to everyone
510
762
  // prevents the first message decryption failure
511
- const sendToAll = !((_a = (0, WABinary_1.jidDecode)(participant)) === null || _a === void 0 ? void 0 : _a.device);
763
+ const sendToAll = !jidDecode(participant)?.device;
764
+ // Check if we should recreate session for this retry
765
+ let shouldRecreateSession = false;
766
+ let recreateReason = '';
767
+ if (enableAutoSessionRecreation && messageRetryManager && retryCount > 1) {
768
+ try {
769
+ const sessionId = signalRepository.jidToSignalProtocolAddress(participant);
770
+ const hasSession = await signalRepository.validateSession(participant);
771
+ const result = messageRetryManager.shouldRecreateSession(participant, hasSession.exists);
772
+ shouldRecreateSession = result.recreate;
773
+ recreateReason = result.reason;
774
+ if (shouldRecreateSession) {
775
+ logger.debug({ participant, retryCount, reason: recreateReason }, 'recreating session for outgoing retry');
776
+ await authState.keys.set({ session: { [sessionId]: null } });
777
+ }
778
+ }
779
+ catch (error) {
780
+ logger.warn({ error, participant }, 'failed to check session recreation for outgoing retry');
781
+ }
782
+ }
512
783
  await assertSessions([participant], true);
513
- if ((0, WABinary_1.isJidGroup)(remoteJid)) {
784
+ if (isJidGroup(remoteJid)) {
514
785
  await authState.keys.set({ 'sender-key-memory': { [remoteJid]: null } });
515
786
  }
516
- logger.debug({ participant, sendToAll }, 'forced new session for retry recp');
787
+ logger.debug({ participant, sendToAll, shouldRecreateSession, recreateReason }, 'forced new session for retry recp');
517
788
  for (const [i, msg] of msgs.entries()) {
518
- if (msg) {
519
- updateSendMessageAgainCount(ids[i], participant);
789
+ if (!ids[i])
790
+ continue;
791
+ if (msg && (await willSendMessageAgain(ids[i], participant))) {
792
+ await updateSendMessageAgainCount(ids[i], participant);
520
793
  const msgRelayOpts = { messageId: ids[i] };
521
794
  if (sendToAll) {
522
795
  msgRelayOpts.useUserDevicesCache = false;
@@ -535,45 +808,42 @@ const makeMessagesRecvSocket = (config) => {
535
808
  }
536
809
  };
537
810
  const handleReceipt = async (node) => {
538
- var _a, _b;
539
811
  const { attrs, content } = node;
540
812
  const isLid = attrs.from.includes('lid');
541
- const isNodeFromMe = (0, WABinary_1.areJidsSameUser)(attrs.participant || attrs.from, isLid ? (_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.lid : (_b = authState.creds.me) === null || _b === void 0 ? void 0 : _b.id);
542
- const remoteJid = !isNodeFromMe || (0, WABinary_1.isJidGroup)(attrs.from) ? attrs.from : attrs.recipient;
543
- const fromMe = !attrs.recipient || (attrs.type === 'retry' && isNodeFromMe);
813
+ const isNodeFromMe = areJidsSameUser(attrs.participant || attrs.from, isLid ? authState.creds.me?.lid : authState.creds.me?.id);
814
+ const remoteJid = !isNodeFromMe || isJidGroup(attrs.from) ? attrs.from : attrs.recipient;
815
+ const fromMe = !attrs.recipient || ((attrs.type === 'retry' || attrs.type === 'sender') && isNodeFromMe);
544
816
  const key = {
545
817
  remoteJid,
546
818
  id: '',
547
819
  fromMe,
548
820
  participant: attrs.participant
549
821
  };
550
- if (shouldIgnoreJid(remoteJid) && remoteJid !== '@s.whatsapp.net') {
822
+ if (shouldIgnoreJid(remoteJid) && remoteJid !== S_WHATSAPP_NET) {
551
823
  logger.debug({ remoteJid }, 'ignoring receipt from jid');
552
824
  await sendMessageAck(node);
553
825
  return;
554
826
  }
555
827
  const ids = [attrs.id];
556
828
  if (Array.isArray(content)) {
557
- const items = (0, WABinary_1.getBinaryNodeChildren)(content[0], 'item');
829
+ const items = getBinaryNodeChildren(content[0], 'item');
558
830
  ids.push(...items.map(i => i.attrs.id));
559
831
  }
560
832
  try {
561
833
  await Promise.all([
562
- processingMutex.mutex(async () => {
563
- const status = (0, Utils_1.getStatusFromReceiptType)(attrs.type);
834
+ receiptMutex.mutex(async () => {
835
+ const status = getStatusFromReceiptType(attrs.type);
564
836
  if (typeof status !== 'undefined' &&
565
- (
566
837
  // basically, we only want to know when a message from us has been delivered to/read by the other person
567
838
  // or another device of ours has read some messages
568
- status >= WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ||
569
- !isNodeFromMe)) {
570
- if ((0, WABinary_1.isJidGroup)(remoteJid) || (0, WABinary_1.isJidStatusBroadcast)(remoteJid)) {
839
+ (status >= proto.WebMessageInfo.Status.SERVER_ACK || !isNodeFromMe)) {
840
+ if (isJidGroup(remoteJid) || isJidStatusBroadcast(remoteJid)) {
571
841
  if (attrs.participant) {
572
- const updateKey = status === WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
842
+ const updateKey = status === proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
573
843
  ev.emit('message-receipt.update', ids.map(id => ({
574
844
  key: { ...key, id },
575
845
  receipt: {
576
- userJid: (0, WABinary_1.jidNormalizedUser)(attrs.participant),
846
+ userJid: jidNormalizedUser(attrs.participant),
577
847
  [updateKey]: +attrs.t
578
848
  }
579
849
  })));
@@ -582,22 +852,23 @@ const makeMessagesRecvSocket = (config) => {
582
852
  else {
583
853
  ev.emit('messages.update', ids.map(id => ({
584
854
  key: { ...key, id },
585
- update: { status }
855
+ update: { status, messageTimestamp: toNumber(+(attrs.t ?? 0)) }
586
856
  })));
587
857
  }
588
858
  }
589
859
  if (attrs.type === 'retry') {
590
860
  // correctly set who is asking for the retry
591
861
  key.participant = key.participant || attrs.from;
592
- const retryNode = (0, WABinary_1.getBinaryNodeChild)(node, 'retry');
593
- if (willSendMessageAgain(ids[0], key.participant)) {
862
+ const retryNode = getBinaryNodeChild(node, 'retry');
863
+ if (ids[0] && key.participant && (await willSendMessageAgain(ids[0], key.participant))) {
594
864
  if (key.fromMe) {
595
865
  try {
866
+ await updateSendMessageAgainCount(ids[0], key.participant);
596
867
  logger.debug({ attrs, key }, 'recv retry request');
597
868
  await sendMessagesAgain(key, ids, retryNode);
598
869
  }
599
870
  catch (error) {
600
- logger.error({ key, ids, trace: error.stack }, 'error in sending message again');
871
+ logger.error({ key, ids, trace: error instanceof Error ? error.stack : 'Unknown error' }, 'error in sending message again');
601
872
  }
602
873
  }
603
874
  else {
@@ -612,219 +883,292 @@ const makeMessagesRecvSocket = (config) => {
612
883
  ]);
613
884
  }
614
885
  finally {
615
- await sendMessageAck(node);
886
+ await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack receipt'));
616
887
  }
617
888
  };
618
889
  const handleNotification = async (node) => {
619
890
  const remoteJid = node.attrs.from;
620
- if (shouldIgnoreJid(remoteJid) && remoteJid !== '@s.whatsapp.net') {
891
+ if (shouldIgnoreJid(remoteJid) && remoteJid !== S_WHATSAPP_NET) {
621
892
  logger.debug({ remoteJid, id: node.attrs.id }, 'ignored notification');
622
893
  await sendMessageAck(node);
623
894
  return;
624
895
  }
625
896
  try {
626
897
  await Promise.all([
627
- processingMutex.mutex(async () => {
628
- var _a;
898
+ notificationMutex.mutex(async () => {
629
899
  const msg = await processNotification(node);
630
900
  if (msg) {
631
- const fromMe = (0, WABinary_1.areJidsSameUser)(node.attrs.participant || remoteJid, authState.creds.me.id);
901
+ const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me.id);
902
+ const { senderAlt: participantAlt, addressingMode } = extractAddressingContext(node);
632
903
  msg.key = {
633
904
  remoteJid,
634
905
  fromMe,
635
906
  participant: node.attrs.participant,
907
+ participantAlt,
908
+ addressingMode,
636
909
  id: node.attrs.id,
637
910
  ...(msg.key || {})
638
911
  };
639
- (_a = msg.participant) !== null && _a !== void 0 ? _a : (msg.participant = node.attrs.participant);
912
+ msg.participant ?? (msg.participant = node.attrs.participant);
640
913
  msg.messageTimestamp = +node.attrs.t;
641
- const fullMsg = WAProto_1.proto.WebMessageInfo.fromObject(msg);
914
+ const fullMsg = proto.WebMessageInfo.fromObject(msg);
642
915
  await upsertMessage(fullMsg, 'append');
643
916
  }
644
917
  })
645
918
  ]);
646
919
  }
647
920
  finally {
648
- await sendMessageAck(node);
921
+ await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack notification'));
649
922
  }
650
923
  };
651
924
  const handleMessage = async (node) => {
652
- var _a, _b, _c;
653
- if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== '@s.whatsapp.net') {
925
+ if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== S_WHATSAPP_NET) {
654
926
  logger.debug({ key: node.attrs.key }, 'ignored message');
655
- await sendMessageAck(node);
927
+ await sendMessageAck(node, NACK_REASONS.UnhandledError);
656
928
  return;
657
929
  }
658
- const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
930
+ const encNode = getBinaryNodeChild(node, 'enc');
659
931
  // TODO: temporary fix for crashes and issues resulting of failed msmsg decryption
660
- if (encNode && encNode.attrs.type === 'msmsg') {
932
+ if (encNode?.attrs.type === 'msmsg') {
661
933
  logger.debug({ key: node.attrs.key }, 'ignored msmsg');
662
- await sendMessageAck(node);
934
+ await sendMessageAck(node, NACK_REASONS.MissingMessageSecret);
663
935
  return;
664
936
  }
665
- let response;
666
- if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable') && !encNode) {
667
- await sendMessageAck(node);
668
- const { key } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '').fullMessage;
669
- response = await requestPlaceholderResend(key);
670
- if (response === 'RESOLVED') {
671
- return;
672
- }
673
- logger.debug('received unavailable message, acked and requested resend from phone');
674
- }
675
- else {
676
- if (placeholderResendCache.get(node.attrs.id)) {
677
- placeholderResendCache.del(node.attrs.id);
678
- }
679
- }
680
- const { fullMessage: msg, category, author, decrypt } = (0, Utils_1.decryptMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
681
- if (response && ((_a = msg === null || msg === void 0 ? void 0 : msg.messageStubParameters) === null || _a === void 0 ? void 0 : _a[0]) === Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT) {
682
- msg.messageStubParameters = [Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT, response];
683
- }
684
- if (((_c = (_b = msg.message) === null || _b === void 0 ? void 0 : _b.protocolMessage) === null || _c === void 0 ? void 0 : _c.type) === WAProto_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER && node.attrs.sender_pn) {
685
- ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn });
686
- }
937
+ let acked = false;
687
938
  try {
688
- await Promise.all([
689
- processingMutex.mutex(async () => {
690
- var _a;
691
- await decrypt();
692
- // message failed to decrypt
693
- if (msg.messageStubType === WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT) {
694
- if (((_a = msg === null || msg === void 0 ? void 0 : msg.messageStubParameters) === null || _a === void 0 ? void 0 : _a[0]) === Utils_1.MISSING_KEYS_ERROR_TEXT) {
695
- return sendMessageAck(node, Utils_1.NACK_REASONS.ParsingError);
939
+ const { fullMessage: msg, category, author, decrypt } = decryptMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
940
+ const alt = msg.key.participantAlt || msg.key.remoteJidAlt;
941
+ // store new mappings we didn't have before
942
+ if (!!alt) {
943
+ const altServer = jidDecode(alt)?.server;
944
+ const primaryJid = msg.key.participant || msg.key.remoteJid;
945
+ if (altServer === 'lid') {
946
+ if (!(await signalRepository.lidMapping.getPNForLID(alt))) {
947
+ await signalRepository.lidMapping.storeLIDPNMappings([{ lid: alt, pn: primaryJid }]);
948
+ await signalRepository.migrateSession(primaryJid, alt);
949
+ }
950
+ }
951
+ else {
952
+ await signalRepository.lidMapping.storeLIDPNMappings([{ lid: primaryJid, pn: alt }]);
953
+ await signalRepository.migrateSession(alt, primaryJid);
954
+ }
955
+ }
956
+ await messageMutex.mutex(async () => {
957
+ await decrypt();
958
+ if (msg.key?.remoteJid && msg.key?.id && msg.message && messageRetryManager) {
959
+ messageRetryManager.addRecentMessage(msg.key.remoteJid, msg.key.id, msg.message);
960
+ }
961
+ // message failed to decrypt
962
+ if (msg.messageStubType === proto.WebMessageInfo.StubType.CIPHERTEXT && msg.category !== 'peer') {
963
+ if (msg?.messageStubParameters?.[0] === MISSING_KEYS_ERROR_TEXT) {
964
+ acked = true;
965
+ return sendMessageAck(node, NACK_REASONS.ParsingError);
966
+ }
967
+ if (msg.messageStubParameters?.[0] === NO_MESSAGE_FOUND_ERROR_TEXT) {
968
+ // Message arrived without encryption (e.g. CTWA ads messages).
969
+ // Check if this is eligible for placeholder resend (matching WA Web filters).
970
+ const unavailableNode = getBinaryNodeChild(node, 'unavailable');
971
+ const unavailableType = unavailableNode?.attrs?.type;
972
+ if (unavailableType === 'bot_unavailable_fanout' ||
973
+ unavailableType === 'hosted_unavailable_fanout' ||
974
+ unavailableType === 'view_once_unavailable_fanout') {
975
+ logger.debug({ msgId: msg.key.id, unavailableType }, 'skipping placeholder resend for excluded unavailable type');
976
+ acked = true;
977
+ return sendMessageAck(node);
978
+ }
979
+ const messageAge = unixTimestampSeconds() - toNumber(msg.messageTimestamp);
980
+ if (messageAge > PLACEHOLDER_MAX_AGE_SECONDS) {
981
+ logger.debug({ msgId: msg.key.id, messageAge }, 'skipping placeholder resend for old message');
982
+ acked = true;
983
+ return sendMessageAck(node);
696
984
  }
697
- retryMutex.mutex(async () => {
698
- if (ws.isOpen) {
699
- if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable')) {
985
+ // Request the real content from the phone via placeholder resend PDO.
986
+ // Upsert the CIPHERTEXT stub as a placeholder (like WA Web's processPlaceholderMsg),
987
+ // and store the requestId in stubParameters[1] so users can correlate
988
+ // with the incoming PDO response event.
989
+ const cleanKey = {
990
+ remoteJid: msg.key.remoteJid,
991
+ fromMe: msg.key.fromMe,
992
+ id: msg.key.id,
993
+ participant: msg.key.participant
994
+ };
995
+ // Cache the original message metadata so the PDO response handler
996
+ // can preserve key fields (LID details etc.) that the phone may omit
997
+ const msgData = {
998
+ key: msg.key,
999
+ messageTimestamp: msg.messageTimestamp,
1000
+ pushName: msg.pushName,
1001
+ participant: msg.participant,
1002
+ verifiedBizName: msg.verifiedBizName
1003
+ };
1004
+ requestPlaceholderResend(cleanKey, msgData)
1005
+ .then(requestId => {
1006
+ if (requestId && requestId !== 'RESOLVED') {
1007
+ logger.debug({ msgId: msg.key.id, requestId }, 'requested placeholder resend for unavailable message');
1008
+ ev.emit('messages.update', [
1009
+ {
1010
+ key: msg.key,
1011
+ update: { messageStubParameters: [NO_MESSAGE_FOUND_ERROR_TEXT, requestId] }
1012
+ }
1013
+ ]);
1014
+ }
1015
+ })
1016
+ .catch(err => {
1017
+ logger.warn({ err, msgId: msg.key.id }, 'failed to request placeholder resend for unavailable message');
1018
+ });
1019
+ acked = true;
1020
+ await sendMessageAck(node);
1021
+ // Don't return — fall through to upsertMessage so the stub is emitted
1022
+ }
1023
+ else {
1024
+ // Skip retry for expired status messages (>24h old)
1025
+ if (isJidStatusBroadcast(msg.key.remoteJid)) {
1026
+ const messageAge = unixTimestampSeconds() - toNumber(msg.messageTimestamp);
1027
+ if (messageAge > STATUS_EXPIRY_SECONDS) {
1028
+ logger.debug({ msgId: msg.key.id, messageAge, remoteJid: msg.key.remoteJid }, 'skipping retry for expired status message');
1029
+ acked = true;
1030
+ return sendMessageAck(node);
1031
+ }
1032
+ }
1033
+ const errorMessage = msg?.messageStubParameters?.[0] || '';
1034
+ const isPreKeyError = errorMessage.includes('PreKey');
1035
+ logger.debug(`[handleMessage] Attempting retry request for failed decryption`);
1036
+ // Handle both pre-key and normal retries in single mutex
1037
+ await retryMutex.mutex(async () => {
1038
+ try {
1039
+ if (!ws.isOpen) {
1040
+ logger.debug({ node }, 'Connection closed, skipping retry');
700
1041
  return;
701
1042
  }
702
- const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
1043
+ // Handle pre-key errors with upload and delay
1044
+ if (isPreKeyError) {
1045
+ logger.info({ error: errorMessage }, 'PreKey error detected, uploading and retrying');
1046
+ try {
1047
+ logger.debug('Uploading pre-keys for error recovery');
1048
+ await uploadPreKeys(5);
1049
+ logger.debug('Waiting for server to process new pre-keys');
1050
+ await delay(1000);
1051
+ }
1052
+ catch (uploadErr) {
1053
+ logger.error({ uploadErr }, 'Pre-key upload failed, proceeding with retry anyway');
1054
+ }
1055
+ }
1056
+ const encNode = getBinaryNodeChild(node, 'enc');
703
1057
  await sendRetryRequest(node, !encNode);
704
1058
  if (retryRequestDelayMs) {
705
- await (0, Utils_1.delay)(retryRequestDelayMs);
1059
+ await delay(retryRequestDelayMs);
706
1060
  }
707
1061
  }
708
- else {
709
- logger.debug({ node }, 'connection closed, ignoring retry req');
1062
+ catch (err) {
1063
+ logger.error({ err, isPreKeyError }, 'Failed to handle retry, attempting basic retry');
1064
+ // Still attempt retry even if pre-key upload failed
1065
+ try {
1066
+ const encNode = getBinaryNodeChild(node, 'enc');
1067
+ await sendRetryRequest(node, !encNode);
1068
+ }
1069
+ catch (retryErr) {
1070
+ logger.error({ retryErr }, 'Failed to send retry after error handling');
1071
+ }
710
1072
  }
1073
+ acked = true;
1074
+ await sendMessageAck(node, NACK_REASONS.UnhandledError);
711
1075
  });
712
1076
  }
713
- else {
1077
+ }
1078
+ else {
1079
+ if (messageRetryManager && msg.key.id) {
1080
+ messageRetryManager.cancelPendingPhoneRequest(msg.key.id);
1081
+ }
1082
+ const isNewsletter = isJidNewsletter(msg.key.remoteJid);
1083
+ if (!isNewsletter) {
714
1084
  // no type in the receipt => message delivered
715
1085
  let type = undefined;
716
1086
  let participant = msg.key.participant;
717
- if (category === 'peer') { // special peer message
1087
+ if (category === 'peer') {
1088
+ // special peer message
718
1089
  type = 'peer_msg';
719
1090
  }
720
- else if (msg.key.fromMe) { // message was sent by us from a different device
1091
+ else if (msg.key.fromMe) {
1092
+ // message was sent by us from a different device
721
1093
  type = 'sender';
722
1094
  // need to specially handle this case
723
- if ((0, WABinary_1.isJidUser)(msg.key.remoteJid)) {
724
- participant = author;
1095
+ if (isLidUser(msg.key.remoteJid) || isLidUser(msg.key.remoteJidAlt)) {
1096
+ participant = author; // TODO: investigate sending receipts to LIDs and not PNs
725
1097
  }
726
1098
  }
727
1099
  else if (!sendActiveReceipts) {
728
1100
  type = 'inactive';
729
1101
  }
1102
+ acked = true;
730
1103
  await sendReceipt(msg.key.remoteJid, participant, [msg.key.id], type);
731
1104
  // send ack for history message
732
- const isAnyHistoryMsg = (0, Utils_1.getHistoryMsg)(msg.message);
1105
+ const isAnyHistoryMsg = getHistoryMsg(msg.message);
733
1106
  if (isAnyHistoryMsg) {
734
- const jid = (0, WABinary_1.jidNormalizedUser)(msg.key.remoteJid);
735
- await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync');
1107
+ const jid = jidNormalizedUser(msg.key.remoteJid);
1108
+ await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync'); // TODO: investigate
736
1109
  }
737
1110
  }
738
- (0, Utils_1.cleanMessage)(msg, authState.creds.me.id);
739
- await sendMessageAck(node);
740
- await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify');
741
- })
742
- ]);
1111
+ else {
1112
+ acked = true;
1113
+ await sendMessageAck(node);
1114
+ logger.debug({ key: msg.key }, 'processed newsletter message without receipts');
1115
+ }
1116
+ }
1117
+ cleanMessage(msg, authState.creds.me.id, authState.creds.me.lid);
1118
+ await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify');
1119
+ });
743
1120
  }
744
1121
  catch (error) {
745
- logger.error({ error, node }, 'error in handling message');
746
- }
747
- };
748
- const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
749
- var _a;
750
- if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
751
- throw new boom_1.Boom('Not authenticated');
1122
+ logger.error({ error, node: binaryNodeToString(node) }, 'error in handling message');
1123
+ if (!acked) {
1124
+ await sendMessageAck(node, NACK_REASONS.UnhandledError).catch(ackErr => logger.error({ ackErr }, 'failed to ack message after error'));
1125
+ }
752
1126
  }
753
- const pdoMessage = {
754
- historySyncOnDemandRequest: {
755
- chatJid: oldestMsgKey.remoteJid,
756
- oldestMsgFromMe: oldestMsgKey.fromMe,
757
- oldestMsgId: oldestMsgKey.id,
758
- oldestMsgTimestampMs: oldestMsgTimestamp,
759
- onDemandMsgCount: count
760
- },
761
- peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
762
- };
763
- return sendPeerDataOperationMessage(pdoMessage);
764
1127
  };
765
- const requestPlaceholderResend = async (messageKey) => {
766
- var _a;
767
- if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
768
- throw new boom_1.Boom('Not authenticated');
769
- }
770
- if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
771
- logger.debug({ messageKey }, 'already requested resend');
772
- return;
1128
+ const handleCall = async (node) => {
1129
+ try {
1130
+ const { attrs } = node;
1131
+ const [infoChild] = getAllBinaryNodeChildren(node);
1132
+ if (!infoChild) {
1133
+ throw new Boom('Missing call info in call node');
1134
+ }
1135
+ const status = getCallStatusFromNode(infoChild);
1136
+ const callId = infoChild.attrs['call-id'];
1137
+ const from = infoChild.attrs.from || infoChild.attrs['call-creator'];
1138
+ const call = {
1139
+ chatId: attrs.from,
1140
+ from,
1141
+ callerPn: infoChild.attrs['caller_pn'],
1142
+ id: callId,
1143
+ date: new Date(+attrs.t * 1000),
1144
+ offline: !!attrs.offline,
1145
+ status
1146
+ };
1147
+ if (status === 'offer') {
1148
+ call.isVideo = !!getBinaryNodeChild(infoChild, 'video');
1149
+ call.isGroup = infoChild.attrs.type === 'group' || !!infoChild.attrs['group-jid'];
1150
+ call.groupJid = infoChild.attrs['group-jid'];
1151
+ await callOfferCache.set(call.id, call);
1152
+ }
1153
+ const existingCall = await callOfferCache.get(call.id);
1154
+ // use existing call info to populate this event
1155
+ if (existingCall) {
1156
+ call.isVideo = existingCall.isVideo;
1157
+ call.isGroup = existingCall.isGroup;
1158
+ call.callerPn = call.callerPn || existingCall.callerPn;
1159
+ }
1160
+ // delete data once call has ended
1161
+ if (status === 'reject' || status === 'accept' || status === 'timeout' || status === 'terminate') {
1162
+ await callOfferCache.del(call.id);
1163
+ }
1164
+ ev.emit('call', [call]);
773
1165
  }
774
- else {
775
- placeholderResendCache.set(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id, true);
1166
+ catch (error) {
1167
+ logger.error({ error, node: binaryNodeToString(node) }, 'error in handling call');
776
1168
  }
777
- await (0, Utils_1.delay)(5000);
778
- if (!placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
779
- logger.debug({ messageKey }, 'message received while resend requested');
780
- return 'RESOLVED';
1169
+ finally {
1170
+ await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack call'));
781
1171
  }
782
- const pdoMessage = {
783
- placeholderMessageResendRequest: [{
784
- messageKey
785
- }],
786
- peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
787
- };
788
- setTimeout(() => {
789
- if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
790
- logger.debug({ messageKey }, 'PDO message without response after 15 seconds. Phone possibly offline');
791
- placeholderResendCache.del(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id);
792
- }
793
- }, 15000);
794
- return sendPeerDataOperationMessage(pdoMessage);
795
- };
796
- const handleCall = async (node) => {
797
- const { attrs } = node;
798
- const [infoChild] = (0, WABinary_1.getAllBinaryNodeChildren)(node);
799
- const callId = infoChild.attrs['call-id'];
800
- const from = infoChild.attrs.from || infoChild.attrs['call-creator'];
801
- const status = (0, Utils_1.getCallStatusFromNode)(infoChild);
802
- const call = {
803
- chatId: attrs.from,
804
- from,
805
- id: callId,
806
- date: new Date(+attrs.t * 1000),
807
- offline: !!attrs.offline,
808
- status,
809
- };
810
- if (status === 'offer') {
811
- call.isVideo = !!(0, WABinary_1.getBinaryNodeChild)(infoChild, 'video');
812
- call.isGroup = infoChild.attrs.type === 'group' || !!infoChild.attrs['group-jid'];
813
- call.groupJid = infoChild.attrs['group-jid'];
814
- callOfferCache.set(call.id, call);
815
- }
816
- const existingCall = callOfferCache.get(call.id);
817
- // use existing call info to populate this event
818
- if (existingCall) {
819
- call.isVideo = existingCall.isVideo;
820
- call.isGroup = existingCall.isGroup;
821
- }
822
- // delete data once call has ended
823
- if (status === 'reject' || status === 'accept' || status === 'timeout' || status === 'terminate') {
824
- callOfferCache.del(call.id);
825
- }
826
- ev.emit('call', [call]);
827
- await sendMessageAck(node);
828
1172
  };
829
1173
  const handleBadAck = async ({ attrs }) => {
830
1174
  const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id };
@@ -849,13 +1193,24 @@ const makeMessagesRecvSocket = (config) => {
849
1193
  {
850
1194
  key,
851
1195
  update: {
852
- status: Types_1.WAMessageStatus.ERROR,
853
- messageStubParameters: [
854
- attrs.error
855
- ]
1196
+ status: WAMessageStatus.ERROR,
1197
+ messageStubParameters: [attrs.error]
856
1198
  }
857
1199
  }
858
1200
  ]);
1201
+ // resend the message with device_fanout=false, use at your own risk
1202
+ // if (attrs.error === '475') {
1203
+ // const msg = await getMessage(key)
1204
+ // if (msg) {
1205
+ // await relayMessage(key.remoteJid!, msg, {
1206
+ // messageId: key.id!,
1207
+ // useUserDevicesCache: false,
1208
+ // additionalAttributes: {
1209
+ // device_fanout: 'false'
1210
+ // }
1211
+ // })
1212
+ // }
1213
+ // }
859
1214
  }
860
1215
  };
861
1216
  /// processes a node with the given function
@@ -865,69 +1220,48 @@ const makeMessagesRecvSocket = (config) => {
865
1220
  await execTask();
866
1221
  ev.flush();
867
1222
  function execTask() {
868
- return exec(node, false)
869
- .catch(err => onUnexpectedError(err, identifier));
1223
+ return exec(node, false).catch(err => onUnexpectedError(err, identifier));
870
1224
  }
871
1225
  };
872
- const makeOfflineNodeProcessor = () => {
873
- const nodeProcessorMap = new Map([
874
- ['message', handleMessage],
875
- ['call', handleCall],
876
- ['receipt', handleReceipt],
877
- ['notification', handleNotification]
878
- ]);
879
- const nodes = [];
880
- let isProcessing = false;
881
- const enqueue = (type, node) => {
882
- nodes.push({ type, node });
883
- if (isProcessing) {
884
- return;
885
- }
886
- isProcessing = true;
887
- const promise = async () => {
888
- while (nodes.length && ws.isOpen) {
889
- const { type, node } = nodes.shift();
890
- const nodeProcessor = nodeProcessorMap.get(type);
891
- if (!nodeProcessor) {
892
- onUnexpectedError(new Error(`unknown offline node type: ${type}`), 'processing offline node');
893
- continue;
894
- }
895
- await nodeProcessor(node);
896
- }
897
- isProcessing = false;
898
- };
899
- promise().catch(error => onUnexpectedError(error, 'processing offline nodes'));
900
- };
901
- return { enqueue };
902
- };
903
- const offlineNodeProcessor = makeOfflineNodeProcessor();
904
- const processNode = (type, node, identifier, exec) => {
1226
+ const offlineNodeProcessor = makeOfflineNodeProcessor(new Map([
1227
+ ['message', handleMessage],
1228
+ ['call', handleCall],
1229
+ ['receipt', handleReceipt],
1230
+ ['notification', handleNotification]
1231
+ ]), {
1232
+ isWsOpen: () => ws.isOpen,
1233
+ onUnexpectedError,
1234
+ yieldToEventLoop: () => new Promise(resolve => setImmediate(resolve))
1235
+ });
1236
+ const processNode = async (type, node, identifier, exec) => {
905
1237
  const isOffline = !!node.attrs.offline;
906
1238
  if (isOffline) {
907
1239
  offlineNodeProcessor.enqueue(type, node);
908
1240
  }
909
1241
  else {
910
- processNodeWithBuffer(node, identifier, exec);
1242
+ await processNodeWithBuffer(node, identifier, exec);
911
1243
  }
912
1244
  };
913
1245
  // recv a message
914
- ws.on('CB:message', (node) => {
915
- processNode('message', node, 'processing message', handleMessage);
1246
+ ws.on('CB:message', async (node) => {
1247
+ await processNode('message', node, 'processing message', handleMessage);
916
1248
  });
917
1249
  ws.on('CB:call', async (node) => {
918
- processNode('call', node, 'handling call', handleCall);
1250
+ await processNode('call', node, 'handling call', handleCall);
919
1251
  });
920
- ws.on('CB:receipt', node => {
921
- processNode('receipt', node, 'handling receipt', handleReceipt);
1252
+ ws.on('CB:receipt', async (node) => {
1253
+ await processNode('receipt', node, 'handling receipt', handleReceipt);
922
1254
  });
923
1255
  ws.on('CB:notification', async (node) => {
924
- processNode('notification', node, 'handling notification', handleNotification);
1256
+ await processNode('notification', node, 'handling notification', handleNotification);
925
1257
  });
926
1258
  ws.on('CB:ack,class:message', (node) => {
927
- handleBadAck(node)
928
- .catch(error => onUnexpectedError(error, 'handling bad ack'));
1259
+ handleBadAck(node).catch(error => onUnexpectedError(error, 'handling bad ack'));
929
1260
  });
930
- ev.on('call', ([call]) => {
1261
+ ev.on('call', async ([call]) => {
1262
+ if (!call) {
1263
+ return;
1264
+ }
931
1265
  // missed call + group call notification message generation
932
1266
  if (call.status === 'timeout' || (call.status === 'offer' && call.isGroup)) {
933
1267
  const msg = {
@@ -936,21 +1270,23 @@ const makeMessagesRecvSocket = (config) => {
936
1270
  id: call.id,
937
1271
  fromMe: false
938
1272
  },
939
- messageTimestamp: (0, Utils_1.unixTimestampSeconds)(call.date),
1273
+ messageTimestamp: unixTimestampSeconds(call.date)
940
1274
  };
941
1275
  if (call.status === 'timeout') {
942
1276
  if (call.isGroup) {
943
- msg.messageStubType = call.isVideo ? Types_1.WAMessageStubType.CALL_MISSED_GROUP_VIDEO : Types_1.WAMessageStubType.CALL_MISSED_GROUP_VOICE;
1277
+ msg.messageStubType = call.isVideo
1278
+ ? WAMessageStubType.CALL_MISSED_GROUP_VIDEO
1279
+ : WAMessageStubType.CALL_MISSED_GROUP_VOICE;
944
1280
  }
945
1281
  else {
946
- msg.messageStubType = call.isVideo ? Types_1.WAMessageStubType.CALL_MISSED_VIDEO : Types_1.WAMessageStubType.CALL_MISSED_VOICE;
1282
+ msg.messageStubType = call.isVideo ? WAMessageStubType.CALL_MISSED_VIDEO : WAMessageStubType.CALL_MISSED_VOICE;
947
1283
  }
948
1284
  }
949
1285
  else {
950
1286
  msg.message = { call: { callKey: Buffer.from(call.id) } };
951
1287
  }
952
- const protoMsg = WAProto_1.proto.WebMessageInfo.fromObject(msg);
953
- upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
1288
+ const protoMsg = proto.WebMessageInfo.fromObject(msg);
1289
+ await upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
954
1290
  }
955
1291
  });
956
1292
  ev.on('connection.update', ({ isOnline }) => {
@@ -963,10 +1299,10 @@ const makeMessagesRecvSocket = (config) => {
963
1299
  ...sock,
964
1300
  sendMessageAck,
965
1301
  sendRetryRequest,
966
- offerCall,
967
1302
  rejectCall,
968
1303
  fetchMessageHistory,
969
1304
  requestPlaceholderResend,
1305
+ messageRetryManager
970
1306
  };
971
1307
  };
972
- exports.makeMessagesRecvSocket = makeMessagesRecvSocket;
1308
+ //# sourceMappingURL=messages-recv.js.map