lordceaser-baileys 2.0.0 → 2.0.2

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 (439) hide show
  1. package/WAProto/index.js +136901 -78899
  2. package/WASignalGroup/GroupProtocol.js +1697 -0
  3. package/WASignalGroup/ciphertext_message.js +16 -0
  4. package/WASignalGroup/group_cipher.js +120 -0
  5. package/WASignalGroup/group_session_builder.js +46 -0
  6. package/WASignalGroup/index.js +5 -0
  7. package/WASignalGroup/keyhelper.js +21 -0
  8. package/WASignalGroup/protobufs.js +3 -0
  9. package/WASignalGroup/queue_job.js +69 -0
  10. package/WASignalGroup/sender_chain_key.js +50 -0
  11. package/WASignalGroup/sender_key_distribution_message.js +78 -0
  12. package/WASignalGroup/sender_key_message.js +92 -0
  13. package/WASignalGroup/sender_key_name.js +70 -0
  14. package/WASignalGroup/sender_key_record.js +56 -0
  15. package/WASignalGroup/sender_key_state.js +129 -0
  16. package/{lib/Signal/Group/sender-message-key.js → WASignalGroup/sender_message_key.js} +16 -3
  17. package/index.js +17 -0
  18. package/lib/Defaults/baileys-version.json +3 -0
  19. package/lib/Defaults/index.d.ts +15 -37
  20. package/lib/Defaults/index.js +60 -81
  21. package/lib/Signal/libsignal.d.ts +3 -5
  22. package/lib/Signal/libsignal.js +80 -359
  23. package/lib/Socket/Client/{types.d.ts → abstract-socket-client.d.ts} +5 -4
  24. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  25. package/lib/Socket/Client/index.d.ts +3 -3
  26. package/lib/Socket/Client/index.js +19 -3
  27. package/lib/Socket/Client/mobile-socket-client.d.ts +13 -0
  28. package/lib/Socket/Client/mobile-socket-client.js +65 -0
  29. package/lib/Socket/Client/{websocket.d.ts → web-socket-client.d.ts} +2 -3
  30. package/lib/Socket/Client/web-socket-client.js +62 -0
  31. package/lib/Socket/business.d.ts +100 -147
  32. package/lib/Socket/business.js +43 -162
  33. package/lib/Socket/chats.d.ts +41 -85
  34. package/lib/Socket/chats.js +321 -569
  35. package/lib/Socket/groups.d.ts +57 -103
  36. package/lib/Socket/groups.js +84 -116
  37. package/lib/Socket/index.d.ts +106 -194
  38. package/lib/Socket/index.js +9 -11
  39. package/lib/Socket/messages-recv.d.ts +89 -134
  40. package/lib/Socket/messages-recv.js +475 -1275
  41. package/lib/Socket/messages-send.d.ts +97 -141
  42. package/lib/Socket/messages-send.js +633 -691
  43. package/lib/Socket/newsletter.d.ts +74 -112
  44. package/lib/Socket/newsletter.js +202 -147
  45. package/lib/Socket/registration.d.ts +264 -0
  46. package/lib/Socket/registration.js +166 -0
  47. package/lib/Socket/socket.d.ts +19 -34
  48. package/lib/Socket/socket.js +219 -547
  49. package/lib/Socket/usync.d.ts +37 -0
  50. package/lib/Socket/usync.js +70 -0
  51. package/lib/Store/index.d.ts +3 -0
  52. package/lib/Store/index.js +10 -0
  53. package/lib/Store/make-cache-manager-store.d.ts +14 -0
  54. package/lib/Store/make-cache-manager-store.js +83 -0
  55. package/lib/Store/make-in-memory-store.d.ts +118 -0
  56. package/lib/Store/make-in-memory-store.js +431 -0
  57. package/lib/Store/make-ordered-dictionary.d.ts +13 -0
  58. package/lib/Store/make-ordered-dictionary.js +81 -0
  59. package/lib/Store/object-repository.d.ts +10 -0
  60. package/lib/Store/object-repository.js +27 -0
  61. package/lib/Types/Auth.d.ts +11 -19
  62. package/lib/Types/Auth.js +2 -2
  63. package/lib/Types/Call.d.ts +1 -3
  64. package/lib/Types/Call.js +2 -2
  65. package/lib/Types/Chat.d.ts +8 -25
  66. package/lib/Types/Chat.js +4 -8
  67. package/lib/Types/Contact.d.ts +1 -8
  68. package/lib/Types/Contact.js +2 -2
  69. package/lib/Types/Events.d.ts +17 -101
  70. package/lib/Types/Events.js +2 -2
  71. package/lib/Types/GroupMetadata.d.ts +3 -18
  72. package/lib/Types/GroupMetadata.js +2 -2
  73. package/lib/Types/Label.d.ts +0 -1
  74. package/lib/Types/Label.js +5 -3
  75. package/lib/Types/LabelAssociation.d.ts +0 -1
  76. package/lib/Types/LabelAssociation.js +5 -3
  77. package/lib/Types/Message.d.ts +204 -91
  78. package/lib/Types/Message.js +9 -11
  79. package/lib/Types/Newsletter.d.ts +92 -0
  80. package/lib/Types/Newsletter.js +32 -0
  81. package/lib/Types/Product.d.ts +1 -2
  82. package/lib/Types/Product.js +2 -2
  83. package/lib/Types/Signal.d.ts +2 -32
  84. package/lib/Types/Signal.js +2 -2
  85. package/lib/Types/Socket.d.ts +24 -44
  86. package/lib/Types/Socket.js +2 -3
  87. package/lib/Types/State.d.ts +2 -72
  88. package/lib/Types/State.js +2 -56
  89. package/lib/Types/USync.d.ts +2 -3
  90. package/lib/Types/USync.js +2 -2
  91. package/lib/Types/index.d.ts +16 -16
  92. package/lib/Types/index.js +31 -15
  93. package/lib/Utils/auth-utils.d.ts +6 -12
  94. package/lib/Utils/auth-utils.js +143 -239
  95. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  96. package/lib/Utils/baileys-event-stream.js +63 -0
  97. package/lib/Utils/business.d.ts +3 -4
  98. package/lib/Utils/business.js +69 -66
  99. package/lib/Utils/c4-compat.js +0 -8
  100. package/lib/Utils/chat-utils.d.ts +17 -47
  101. package/lib/Utils/chat-utils.js +237 -364
  102. package/lib/Utils/crypto.d.ts +21 -18
  103. package/lib/Utils/crypto.js +125 -44
  104. package/lib/Utils/decode-wa-message.d.ts +8 -38
  105. package/lib/Utils/decode-wa-message.js +90 -173
  106. package/lib/Utils/event-buffer.d.ts +8 -9
  107. package/lib/Utils/event-buffer.js +71 -176
  108. package/lib/Utils/generics.d.ts +22 -26
  109. package/lib/Utils/generics.js +175 -166
  110. package/lib/Utils/history.d.ts +11 -16
  111. package/lib/Utils/history.js +53 -93
  112. package/lib/Utils/index.d.ts +17 -22
  113. package/lib/Utils/index.js +34 -22
  114. package/lib/Utils/link-preview.d.ts +5 -5
  115. package/lib/Utils/link-preview.js +24 -16
  116. package/lib/Utils/logger.d.ts +1 -11
  117. package/lib/Utils/logger.js +7 -3
  118. package/lib/Utils/lt-hash.d.ts +12 -8
  119. package/lib/Utils/lt-hash.js +46 -3
  120. package/lib/Utils/make-mutex.d.ts +0 -2
  121. package/lib/Utils/make-mutex.js +34 -24
  122. package/lib/Utils/messages-media.d.ts +45 -65
  123. package/lib/Utils/messages-media.js +358 -425
  124. package/lib/Utils/messages.d.ts +18 -32
  125. package/lib/Utils/messages.js +720 -392
  126. package/lib/Utils/noise-handler.d.ts +13 -13
  127. package/lib/Utils/noise-handler.js +108 -149
  128. package/lib/Utils/process-message.d.ts +11 -30
  129. package/lib/Utils/process-message.js +166 -423
  130. package/lib/Utils/signal.d.ts +6 -20
  131. package/lib/Utils/signal.js +65 -107
  132. package/lib/Utils/use-multi-file-auth-state.d.ts +1 -2
  133. package/lib/Utils/use-multi-file-auth-state.js +103 -57
  134. package/lib/Utils/use-single-file-auth-state.d.ts +12 -0
  135. package/lib/Utils/use-single-file-auth-state.js +76 -0
  136. package/lib/Utils/validate-connection.d.ts +6 -6
  137. package/lib/Utils/validate-connection.js +114 -119
  138. package/lib/WABinary/constants.d.ts +4 -5
  139. package/lib/WABinary/constants.js +20 -1281
  140. package/lib/WABinary/decode.d.ts +3 -4
  141. package/lib/WABinary/decode.js +53 -51
  142. package/lib/WABinary/encode.d.ts +1 -2
  143. package/lib/WABinary/encode.js +44 -12
  144. package/lib/WABinary/generic-utils.d.ts +6 -7
  145. package/lib/WABinary/generic-utils.js +43 -46
  146. package/lib/WABinary/index.d.ts +5 -6
  147. package/lib/WABinary/index.js +21 -6
  148. package/lib/WABinary/jid-utils.d.ts +7 -24
  149. package/lib/WABinary/jid-utils.js +40 -74
  150. package/lib/WABinary/types.d.ts +1 -2
  151. package/lib/WABinary/types.js +2 -2
  152. package/lib/WAM/BinaryInfo.d.ts +1 -2
  153. package/lib/WAM/BinaryInfo.js +5 -2
  154. package/lib/WAM/constants.d.ts +3 -5
  155. package/lib/WAM/constants.js +11958 -19461
  156. package/lib/WAM/encode.d.ts +2 -3
  157. package/lib/WAM/encode.js +22 -17
  158. package/lib/WAM/index.d.ts +3 -4
  159. package/lib/WAM/index.js +19 -4
  160. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +3 -4
  161. package/lib/WAUSync/Protocols/USyncContactProtocol.js +13 -33
  162. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +2 -3
  163. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +14 -11
  164. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +2 -3
  165. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +12 -9
  166. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +2 -3
  167. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +13 -9
  168. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +3 -4
  169. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +22 -20
  170. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +3 -5
  171. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +8 -13
  172. package/lib/WAUSync/Protocols/index.d.ts +4 -6
  173. package/lib/WAUSync/Protocols/index.js +20 -6
  174. package/lib/WAUSync/USyncQuery.d.ts +4 -6
  175. package/lib/WAUSync/USyncQuery.js +35 -44
  176. package/lib/WAUSync/USyncUser.d.ts +4 -11
  177. package/lib/WAUSync/USyncUser.js +5 -10
  178. package/lib/WAUSync/index.d.ts +3 -4
  179. package/lib/WAUSync/index.js +19 -4
  180. package/lib/index.js +31 -13
  181. package/package.json +19 -10
  182. package/WAProto/GenerateStatics.sh +0 -3
  183. package/WAProto/WAProto.proto +0 -5479
  184. package/WAProto/fix-imports.js +0 -85
  185. package/WAProto/index.d.ts +0 -14017
  186. package/lib/Defaults/index.d.ts.map +0 -1
  187. package/lib/Defaults/index.js.map +0 -1
  188. package/lib/Signal/Group/ciphertext-message.d.ts +0 -10
  189. package/lib/Signal/Group/ciphertext-message.d.ts.map +0 -1
  190. package/lib/Signal/Group/ciphertext-message.js +0 -12
  191. package/lib/Signal/Group/ciphertext-message.js.map +0 -1
  192. package/lib/Signal/Group/group-session-builder.d.ts +0 -15
  193. package/lib/Signal/Group/group-session-builder.d.ts.map +0 -1
  194. package/lib/Signal/Group/group-session-builder.js +0 -30
  195. package/lib/Signal/Group/group-session-builder.js.map +0 -1
  196. package/lib/Signal/Group/group_cipher.d.ts +0 -17
  197. package/lib/Signal/Group/group_cipher.d.ts.map +0 -1
  198. package/lib/Signal/Group/group_cipher.js +0 -82
  199. package/lib/Signal/Group/group_cipher.js.map +0 -1
  200. package/lib/Signal/Group/index.d.ts +0 -12
  201. package/lib/Signal/Group/index.d.ts.map +0 -1
  202. package/lib/Signal/Group/index.js +0 -12
  203. package/lib/Signal/Group/index.js.map +0 -1
  204. package/lib/Signal/Group/keyhelper.d.ts +0 -11
  205. package/lib/Signal/Group/keyhelper.d.ts.map +0 -1
  206. package/lib/Signal/Group/keyhelper.js +0 -18
  207. package/lib/Signal/Group/keyhelper.js.map +0 -1
  208. package/lib/Signal/Group/sender-chain-key.d.ts +0 -14
  209. package/lib/Signal/Group/sender-chain-key.d.ts.map +0 -1
  210. package/lib/Signal/Group/sender-chain-key.js +0 -26
  211. package/lib/Signal/Group/sender-chain-key.js.map +0 -1
  212. package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -17
  213. package/lib/Signal/Group/sender-key-distribution-message.d.ts.map +0 -1
  214. package/lib/Signal/Group/sender-key-distribution-message.js +0 -63
  215. package/lib/Signal/Group/sender-key-distribution-message.js.map +0 -1
  216. package/lib/Signal/Group/sender-key-message.d.ts +0 -19
  217. package/lib/Signal/Group/sender-key-message.d.ts.map +0 -1
  218. package/lib/Signal/Group/sender-key-message.js +0 -66
  219. package/lib/Signal/Group/sender-key-message.js.map +0 -1
  220. package/lib/Signal/Group/sender-key-name.d.ts +0 -18
  221. package/lib/Signal/Group/sender-key-name.d.ts.map +0 -1
  222. package/lib/Signal/Group/sender-key-name.js +0 -48
  223. package/lib/Signal/Group/sender-key-name.js.map +0 -1
  224. package/lib/Signal/Group/sender-key-record.d.ts +0 -31
  225. package/lib/Signal/Group/sender-key-record.d.ts.map +0 -1
  226. package/lib/Signal/Group/sender-key-record.js +0 -41
  227. package/lib/Signal/Group/sender-key-record.js.map +0 -1
  228. package/lib/Signal/Group/sender-key-state.d.ts +0 -39
  229. package/lib/Signal/Group/sender-key-state.d.ts.map +0 -1
  230. package/lib/Signal/Group/sender-key-state.js +0 -84
  231. package/lib/Signal/Group/sender-key-state.js.map +0 -1
  232. package/lib/Signal/Group/sender-message-key.d.ts +0 -12
  233. package/lib/Signal/Group/sender-message-key.d.ts.map +0 -1
  234. package/lib/Signal/Group/sender-message-key.js.map +0 -1
  235. package/lib/Signal/libsignal.d.ts.map +0 -1
  236. package/lib/Signal/libsignal.js.map +0 -1
  237. package/lib/Signal/lid-mapping.d.ts +0 -23
  238. package/lib/Signal/lid-mapping.d.ts.map +0 -1
  239. package/lib/Signal/lid-mapping.js +0 -277
  240. package/lib/Signal/lid-mapping.js.map +0 -1
  241. package/lib/Socket/Client/index.d.ts.map +0 -1
  242. package/lib/Socket/Client/index.js.map +0 -1
  243. package/lib/Socket/Client/types.d.ts.map +0 -1
  244. package/lib/Socket/Client/types.js +0 -11
  245. package/lib/Socket/Client/types.js.map +0 -1
  246. package/lib/Socket/Client/websocket.d.ts.map +0 -1
  247. package/lib/Socket/Client/websocket.js +0 -54
  248. package/lib/Socket/Client/websocket.js.map +0 -1
  249. package/lib/Socket/business.d.ts.map +0 -1
  250. package/lib/Socket/business.js.map +0 -1
  251. package/lib/Socket/chats.d.ts.map +0 -1
  252. package/lib/Socket/chats.js.map +0 -1
  253. package/lib/Socket/communities.d.ts +0 -273
  254. package/lib/Socket/communities.d.ts.map +0 -1
  255. package/lib/Socket/communities.js +0 -431
  256. package/lib/Socket/communities.js.map +0 -1
  257. package/lib/Socket/groups.d.ts.map +0 -1
  258. package/lib/Socket/groups.js.map +0 -1
  259. package/lib/Socket/index.d.ts.map +0 -1
  260. package/lib/Socket/index.js.map +0 -1
  261. package/lib/Socket/messages-recv.d.ts.map +0 -1
  262. package/lib/Socket/messages-recv.js.map +0 -1
  263. package/lib/Socket/messages-send.d.ts.map +0 -1
  264. package/lib/Socket/messages-send.js.map +0 -1
  265. package/lib/Socket/mex.d.ts +0 -3
  266. package/lib/Socket/mex.d.ts.map +0 -1
  267. package/lib/Socket/mex.js +0 -42
  268. package/lib/Socket/mex.js.map +0 -1
  269. package/lib/Socket/newsletter.d.ts.map +0 -1
  270. package/lib/Socket/newsletter.js.map +0 -1
  271. package/lib/Socket/socket.d.ts.map +0 -1
  272. package/lib/Socket/socket.js.map +0 -1
  273. package/lib/Types/Auth.d.ts.map +0 -1
  274. package/lib/Types/Auth.js.map +0 -1
  275. package/lib/Types/Bussines.d.ts +0 -25
  276. package/lib/Types/Bussines.d.ts.map +0 -1
  277. package/lib/Types/Bussines.js +0 -2
  278. package/lib/Types/Bussines.js.map +0 -1
  279. package/lib/Types/Call.d.ts.map +0 -1
  280. package/lib/Types/Call.js.map +0 -1
  281. package/lib/Types/Chat.d.ts.map +0 -1
  282. package/lib/Types/Chat.js.map +0 -1
  283. package/lib/Types/Contact.d.ts.map +0 -1
  284. package/lib/Types/Contact.js.map +0 -1
  285. package/lib/Types/Events.d.ts.map +0 -1
  286. package/lib/Types/Events.js.map +0 -1
  287. package/lib/Types/GroupMetadata.d.ts.map +0 -1
  288. package/lib/Types/GroupMetadata.js.map +0 -1
  289. package/lib/Types/Label.d.ts.map +0 -1
  290. package/lib/Types/Label.js.map +0 -1
  291. package/lib/Types/LabelAssociation.d.ts.map +0 -1
  292. package/lib/Types/LabelAssociation.js.map +0 -1
  293. package/lib/Types/Message.d.ts.map +0 -1
  294. package/lib/Types/Message.js.map +0 -1
  295. package/lib/Types/Mex.d.ts +0 -141
  296. package/lib/Types/Mex.d.ts.map +0 -1
  297. package/lib/Types/Mex.js +0 -37
  298. package/lib/Types/Mex.js.map +0 -1
  299. package/lib/Types/Product.d.ts.map +0 -1
  300. package/lib/Types/Product.js.map +0 -1
  301. package/lib/Types/Signal.d.ts.map +0 -1
  302. package/lib/Types/Signal.js.map +0 -1
  303. package/lib/Types/Socket.d.ts.map +0 -1
  304. package/lib/Types/Socket.js.map +0 -1
  305. package/lib/Types/State.d.ts.map +0 -1
  306. package/lib/Types/State.js.map +0 -1
  307. package/lib/Types/USync.d.ts.map +0 -1
  308. package/lib/Types/USync.js.map +0 -1
  309. package/lib/Types/index.d.ts.map +0 -1
  310. package/lib/Types/index.js.map +0 -1
  311. package/lib/Utils/auth-utils.d.ts.map +0 -1
  312. package/lib/Utils/auth-utils.js.map +0 -1
  313. package/lib/Utils/browser-utils.d.ts +0 -4
  314. package/lib/Utils/browser-utils.d.ts.map +0 -1
  315. package/lib/Utils/browser-utils.js +0 -29
  316. package/lib/Utils/browser-utils.js.map +0 -1
  317. package/lib/Utils/business.d.ts.map +0 -1
  318. package/lib/Utils/business.js.map +0 -1
  319. package/lib/Utils/chat-utils.d.ts.map +0 -1
  320. package/lib/Utils/chat-utils.js.map +0 -1
  321. package/lib/Utils/companion-reg-client-utils.d.ts +0 -17
  322. package/lib/Utils/companion-reg-client-utils.d.ts.map +0 -1
  323. package/lib/Utils/companion-reg-client-utils.js +0 -35
  324. package/lib/Utils/companion-reg-client-utils.js.map +0 -1
  325. package/lib/Utils/crypto.d.ts.map +0 -1
  326. package/lib/Utils/crypto.js.map +0 -1
  327. package/lib/Utils/decode-wa-message.d.ts.map +0 -1
  328. package/lib/Utils/decode-wa-message.js.map +0 -1
  329. package/lib/Utils/event-buffer.d.ts.map +0 -1
  330. package/lib/Utils/event-buffer.js.map +0 -1
  331. package/lib/Utils/generics.d.ts.map +0 -1
  332. package/lib/Utils/generics.js.map +0 -1
  333. package/lib/Utils/history.d.ts.map +0 -1
  334. package/lib/Utils/history.js.map +0 -1
  335. package/lib/Utils/identity-change-handler.d.ts +0 -44
  336. package/lib/Utils/identity-change-handler.d.ts.map +0 -1
  337. package/lib/Utils/identity-change-handler.js +0 -50
  338. package/lib/Utils/identity-change-handler.js.map +0 -1
  339. package/lib/Utils/index.d.ts.map +0 -1
  340. package/lib/Utils/index.js.map +0 -1
  341. package/lib/Utils/link-preview.d.ts.map +0 -1
  342. package/lib/Utils/link-preview.js.map +0 -1
  343. package/lib/Utils/logger.d.ts.map +0 -1
  344. package/lib/Utils/logger.js.map +0 -1
  345. package/lib/Utils/lt-hash.d.ts.map +0 -1
  346. package/lib/Utils/lt-hash.js.map +0 -1
  347. package/lib/Utils/make-mutex.d.ts.map +0 -1
  348. package/lib/Utils/make-mutex.js.map +0 -1
  349. package/lib/Utils/message-retry-manager.d.ts +0 -115
  350. package/lib/Utils/message-retry-manager.d.ts.map +0 -1
  351. package/lib/Utils/message-retry-manager.js +0 -265
  352. package/lib/Utils/message-retry-manager.js.map +0 -1
  353. package/lib/Utils/messages-media.d.ts.map +0 -1
  354. package/lib/Utils/messages-media.js.map +0 -1
  355. package/lib/Utils/messages.d.ts.map +0 -1
  356. package/lib/Utils/messages.js.map +0 -1
  357. package/lib/Utils/noise-handler.d.ts.map +0 -1
  358. package/lib/Utils/noise-handler.js.map +0 -1
  359. package/lib/Utils/offline-node-processor.d.ts +0 -17
  360. package/lib/Utils/offline-node-processor.d.ts.map +0 -1
  361. package/lib/Utils/offline-node-processor.js +0 -40
  362. package/lib/Utils/offline-node-processor.js.map +0 -1
  363. package/lib/Utils/pre-key-manager.d.ts +0 -28
  364. package/lib/Utils/pre-key-manager.d.ts.map +0 -1
  365. package/lib/Utils/pre-key-manager.js +0 -106
  366. package/lib/Utils/pre-key-manager.js.map +0 -1
  367. package/lib/Utils/process-message.d.ts.map +0 -1
  368. package/lib/Utils/process-message.js.map +0 -1
  369. package/lib/Utils/reporting-utils.d.ts +0 -11
  370. package/lib/Utils/reporting-utils.d.ts.map +0 -1
  371. package/lib/Utils/reporting-utils.js +0 -258
  372. package/lib/Utils/reporting-utils.js.map +0 -1
  373. package/lib/Utils/signal.d.ts.map +0 -1
  374. package/lib/Utils/signal.js.map +0 -1
  375. package/lib/Utils/stanza-ack.d.ts +0 -11
  376. package/lib/Utils/stanza-ack.d.ts.map +0 -1
  377. package/lib/Utils/stanza-ack.js +0 -38
  378. package/lib/Utils/stanza-ack.js.map +0 -1
  379. package/lib/Utils/sync-action-utils.d.ts +0 -19
  380. package/lib/Utils/sync-action-utils.d.ts.map +0 -1
  381. package/lib/Utils/sync-action-utils.js +0 -49
  382. package/lib/Utils/sync-action-utils.js.map +0 -1
  383. package/lib/Utils/tc-token-utils.d.ts +0 -37
  384. package/lib/Utils/tc-token-utils.d.ts.map +0 -1
  385. package/lib/Utils/tc-token-utils.js +0 -164
  386. package/lib/Utils/tc-token-utils.js.map +0 -1
  387. package/lib/Utils/use-multi-file-auth-state.d.ts.map +0 -1
  388. package/lib/Utils/use-multi-file-auth-state.js.map +0 -1
  389. package/lib/Utils/validate-connection.d.ts.map +0 -1
  390. package/lib/Utils/validate-connection.js.map +0 -1
  391. package/lib/WABinary/constants.d.ts.map +0 -1
  392. package/lib/WABinary/constants.js.map +0 -1
  393. package/lib/WABinary/decode.d.ts.map +0 -1
  394. package/lib/WABinary/decode.js.map +0 -1
  395. package/lib/WABinary/encode.d.ts.map +0 -1
  396. package/lib/WABinary/encode.js.map +0 -1
  397. package/lib/WABinary/generic-utils.d.ts.map +0 -1
  398. package/lib/WABinary/generic-utils.js.map +0 -1
  399. package/lib/WABinary/index.d.ts.map +0 -1
  400. package/lib/WABinary/index.js.map +0 -1
  401. package/lib/WABinary/jid-utils.d.ts.map +0 -1
  402. package/lib/WABinary/jid-utils.js.map +0 -1
  403. package/lib/WABinary/types.d.ts.map +0 -1
  404. package/lib/WABinary/types.js.map +0 -1
  405. package/lib/WAM/BinaryInfo.d.ts.map +0 -1
  406. package/lib/WAM/BinaryInfo.js.map +0 -1
  407. package/lib/WAM/constants.d.ts.map +0 -1
  408. package/lib/WAM/constants.js.map +0 -1
  409. package/lib/WAM/encode.d.ts.map +0 -1
  410. package/lib/WAM/encode.js.map +0 -1
  411. package/lib/WAM/index.d.ts.map +0 -1
  412. package/lib/WAM/index.js.map +0 -1
  413. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +0 -1
  414. package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +0 -1
  415. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +0 -1
  416. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +0 -1
  417. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +0 -1
  418. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +0 -1
  419. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +0 -1
  420. package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +0 -1
  421. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +0 -10
  422. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +0 -1
  423. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +0 -25
  424. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +0 -1
  425. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts.map +0 -1
  426. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js.map +0 -1
  427. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +0 -1
  428. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +0 -1
  429. package/lib/WAUSync/Protocols/index.d.ts.map +0 -1
  430. package/lib/WAUSync/Protocols/index.js.map +0 -1
  431. package/lib/WAUSync/USyncQuery.d.ts.map +0 -1
  432. package/lib/WAUSync/USyncQuery.js.map +0 -1
  433. package/lib/WAUSync/USyncUser.d.ts.map +0 -1
  434. package/lib/WAUSync/USyncUser.js.map +0 -1
  435. package/lib/WAUSync/index.d.ts.map +0 -1
  436. package/lib/WAUSync/index.js.map +0 -1
  437. package/lib/index.d.ts +0 -12
  438. package/lib/index.d.ts.map +0 -1
  439. package/lib/index.js.map +0 -1
@@ -1,465 +1,157 @@
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 { ReachoutTimelockEnforcementType, WAMessageStatus, WAMessageStubType } from '../Types/index.js';
8
- import { ACCOUNT_RESTRICTED_TEXT, aesDecryptCTR, aesEncryptGCM, cleanMessage, Curve, decodeMediaRetryNode, decodeMessageNode, decryptMessageNode, delay, derivePairingCodeKey, encodeBigEndian, encodeSignedDeviceIdentity, extractAddressingContext, extractE2ESessionFromRetryReceipt, getCallStatusFromNode, getHistoryMsg, getNextPreKeys, getStatusFromReceiptType, handleIdentityChange, hkdf, MISSING_KEYS_ERROR_TEXT, NACK_REASONS, NO_MESSAGE_FOUND_ERROR_TEXT, SERVER_ERROR_CODES, 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 { buildMergedTcTokenIndexWrite, isTcTokenExpired, readTcTokenIndex, resolveIssuanceJid, resolveTcTokenJid, storeTcTokensFromIqResult, TC_TOKEN_INDEX_KEY } from '../Utils/tc-token-utils.js';
13
- import { areJidsSameUser, binaryNodeToString, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildren, getBinaryNodeChildString, getBinaryNodeChildUInt, isJidGroup, isJidNewsletter, isJidStatusBroadcast, isLidUser, isPnUser, jidDecode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
14
- import { extractGroupMetadata } from './groups.js';
15
- import { makeMessagesSocket } from './messages-send.js';
16
- const ENFORCEMENT_TYPE_VALUES = new Set(Object.values(ReachoutTimelockEnforcementType));
17
- function isValidEnforcementType(value) {
18
- return typeof value === 'string' && ENFORCEMENT_TYPE_VALUES.has(value);
19
- }
20
- export const makeMessagesRecvSocket = (config) => {
21
- const { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid, enableAutoSessionRecreation } = config;
22
- const sock = makeMessagesSocket(config);
23
- const { userDevicesCache, devicesMutex, ev, authState, ws, messageMutex, notificationMutex, receiptMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage, messageRetryManager, registerSocketEndHandler, issuePrivacyTokens, fetchAccountReachoutTimelock, placeholderResendCache } = sock;
24
- const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
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;
25
22
  /** this mutex ensures that each retryRequest will wait for the previous one to finish */
26
- const retryMutex = makeMutex();
27
- const msgRetryCache = config.msgRetryCounterCache ||
28
- new NodeCache({
29
- stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
30
- useClones: false
31
- });
32
- const callOfferCache = config.callOfferCache ||
33
- new NodeCache({
34
- stdTTL: DEFAULT_CACHE_TTLS.CALL_OFFER, // 5 mins
35
- useClones: false
36
- });
37
- // Debounce identity-change session refreshes per JID to avoid bursts
38
- const identityAssertDebounce = new NodeCache({ stdTTL: 5, useClones: false });
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
+ });
39
36
  let sendActiveReceipts = false;
40
- const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
41
- if (!authState.creds.me?.id) {
42
- throw new Boom('Not authenticated');
43
- }
44
- const pdoMessage = {
45
- historySyncOnDemandRequest: {
46
- chatJid: oldestMsgKey.remoteJid,
47
- oldestMsgFromMe: oldestMsgKey.fromMe,
48
- oldestMsgId: oldestMsgKey.id,
49
- oldestMsgTimestampMs: oldestMsgTimestamp,
50
- onDemandMsgCount: count
51
- },
52
- peerDataOperationRequestType: proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
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
+ }
53
45
  };
54
- return sendPeerDataOperationMessage(pdoMessage);
55
- };
56
- const requestPlaceholderResend = async (messageKey, msgData) => {
57
- if (!authState.creds.me?.id) {
58
- throw new Boom('Not authenticated');
46
+ if (!!errorCode) {
47
+ stanza.attrs.error = errorCode.toString();
59
48
  }
60
- if (await placeholderResendCache.get(messageKey?.id)) {
61
- logger.debug({ messageKey }, 'already requested resend');
62
- return;
49
+ if (!!attrs.participant) {
50
+ stanza.attrs.participant = attrs.participant;
63
51
  }
64
- else {
65
- // Store original message data so PDO response handler can preserve
66
- // metadata (LID details, timestamps, etc.) that the phone may omit
67
- await placeholderResendCache.set(messageKey?.id, msgData || true);
52
+ if (!!attrs.recipient) {
53
+ stanza.attrs.recipient = attrs.recipient;
68
54
  }
69
- await delay(2000);
70
- if (!(await placeholderResendCache.get(messageKey?.id))) {
71
- logger.debug({ messageKey }, 'message received while resend requested');
72
- return 'RESOLVED';
55
+ if (!!attrs.type && (tag !== 'message' || (0, WABinary_1.getBinaryNodeChild)({ tag, attrs, content }, 'unavailable') || errorCode !== 0)) {
56
+ stanza.attrs.type = attrs.type;
73
57
  }
74
- const pdoMessage = {
75
- placeholderMessageResendRequest: [
76
- {
77
- messageKey
78
- }
79
- ],
80
- peerDataOperationRequestType: proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
81
- };
82
- setTimeout(async () => {
83
- if (await placeholderResendCache.get(messageKey?.id)) {
84
- logger.debug({ messageKey }, 'PDO message without response after 8 seconds. Phone possibly offline');
85
- await placeholderResendCache.del(messageKey?.id);
86
- }
87
- }, 8000);
88
- return sendPeerDataOperationMessage(pdoMessage);
89
- };
90
- const handleMexNotification = async (node) => {
91
- const updateNode = getBinaryNodeChild(node, 'update');
92
- if (updateNode) {
93
- const opName = updateNode.attrs?.op_name;
94
- if (!opName) {
95
- logger.warn({ node: binaryNodeToString(node) }, 'mex notification missing op_name, fallback to legacy');
96
- await handleLegacyMexNewsletterNotification(node);
97
- return;
98
- }
99
- let mexResponse;
100
- try {
101
- mexResponse = JSON.parse(updateNode.content.toString());
102
- }
103
- catch (error) {
104
- logger.error({ err: error, opName }, 'failed to parse mex notification JSON');
105
- return;
106
- }
107
- if (mexResponse.errors?.length) {
108
- logger.warn({ errors: mexResponse.errors, opName }, 'mex notification has GQL errors');
109
- return;
110
- }
111
- const data = mexResponse.data;
112
- if (!data) {
113
- logger.warn({ opName }, 'mex notification has null data');
114
- return;
115
- }
116
- logger.debug({ opName }, 'processing mex notification');
117
- switch (opName) {
118
- case 'NotificationUserReachoutTimelockUpdate':
119
- handleReachoutTimelockNotification(data);
120
- break;
121
- case 'MessageCappingInfoNotification':
122
- handleMessageCappingNotification(data);
123
- break;
124
- // newsletter ops still use the legacy <mex> child structure
125
- case 'NotificationNewsletterUpdate':
126
- case 'NotificationLinkedProfilesUpdates':
127
- case 'NotificationNewsletterAdminPromote':
128
- case 'NotificationNewsletterAdminDemote':
129
- case 'NotificationNewsletterUserSettingChange':
130
- case 'NotificationNewsletterJoin':
131
- case 'NotificationNewsletterLeave':
132
- case 'NotificationNewsletterStateChange':
133
- case 'NotificationNewsletterAdminMetadataUpdate':
134
- case 'NotificationNewsletterOwnerUpdate':
135
- case 'NotificationNewsletterAdminInviteRevoke':
136
- case 'NotificationNewsletterWamoSubStatusChange':
137
- case 'NotificationNewsletterBlockUser':
138
- case 'NotificationNewsletterPaidPartnership':
139
- case 'NotificationNewsletterMilestone':
140
- case 'NewsletterResponseStateUpdate':
141
- await handleLegacyMexNewsletterNotification(node);
142
- break;
143
- default:
144
- logger.debug({ opName }, 'unhandled mex notification');
145
- break;
146
- }
147
- return;
58
+ if (tag === 'message' && (0, WABinary_1.getBinaryNodeChild)({ tag, attrs, content }, 'unavailable')) {
59
+ stanza.attrs.from = authState.creds.me.id;
148
60
  }
149
- await handleLegacyMexNewsletterNotification(node);
61
+ logger.debug({ recv: { tag, attrs }, sent: stanza.attrs }, 'sent ack');
62
+ await sendNode(stanza);
150
63
  };
151
- const handleReachoutTimelockNotification = (data) => {
152
- const payload = data.xwa2_notify_account_reachout_timelock;
153
- if (!payload) {
154
- logger.warn('reachout timelock notification missing payload');
155
- return;
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
+ });
156
75
  }
157
- if (!payload.is_active) {
158
- logger.info('reachout timelock restriction lifted');
159
- ev.emit('connection.update', {
160
- reachoutTimeLock: {
161
- isActive: false,
162
- enforcementType: ReachoutTimelockEnforcementType.DEFAULT
163
- }
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)
164
93
  });
165
- return;
166
94
  }
167
- // WA Web defaults to now+60s when the server omits the expiry
168
- const timeEnforcementEnds = payload.time_enforcement_ends
169
- ? new Date(parseInt(payload.time_enforcement_ends, 10) * 1000)
170
- : new Date(Date.now() + 60000);
171
- const enforcementType = isValidEnforcementType(payload.enforcement_type)
172
- ? payload.enforcement_type
173
- : ReachoutTimelockEnforcementType.DEFAULT;
174
- logger.info({ enforcementType, timeEnforcementEnds }, 'reachout timelock restriction set');
175
- ev.emit('connection.update', {
176
- reachoutTimeLock: {
177
- isActive: true,
178
- timeEnforcementEnds,
179
- enforcementType
180
- }
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
+ }],
181
109
  });
182
- };
183
- const handleMessageCappingNotification = (data) => {
184
- const payload = data.xwa2_notify_new_chat_messages_capping_info_update;
185
- if (!payload) {
186
- logger.warn('message capping notification missing payload');
187
- return;
188
- }
189
- logger.info({ payload }, 'received message capping update');
190
- ev.emit('message-capping.update', payload);
191
- };
192
- const handleLegacyMexNewsletterNotification = async (node) => {
193
- const mexNode = getBinaryNodeChild(node, 'mex');
194
- const updateNode = mexNode?.content ? null : getBinaryNodeChild(node, 'update') || getAllBinaryNodeChildren(node)[0];
195
- const payloadNode = mexNode?.content ? mexNode : updateNode;
196
- if (!payloadNode?.content) {
197
- logger.warn({ node: binaryNodeToString(node) }, 'invalid mex newsletter notification');
198
- return;
199
- }
200
- let data;
201
- try {
202
- const payloadContent = payloadNode.content;
203
- if (Array.isArray(payloadContent)) {
204
- logger.warn({ payloadNode }, 'invalid mex newsletter notification payload format');
205
- return;
206
- }
207
- const contentBuf = typeof payloadContent === 'string' ? Buffer.from(payloadContent, 'binary') : Buffer.from(payloadContent);
208
- data = JSON.parse(contentBuf.toString());
209
- }
210
- catch (error) {
211
- logger.error({ err: error, node: binaryNodeToString(node) }, 'failed to parse mex newsletter notification');
212
- return;
213
- }
214
- const operation = data?.operation ?? payloadNode?.attrs?.op_name;
215
- let updates = data?.updates;
216
- if (!updates) {
217
- const linkedProfiles = data?.data?.xwa2_notify_linked_profiles;
218
- if (linkedProfiles) {
219
- updates = [linkedProfiles];
220
- }
221
- }
222
- if (!updates || !operation) {
223
- logger.warn({ data }, 'invalid mex newsletter notification content');
224
- return;
225
- }
226
- logger.info({ operation, updates }, 'got mex newsletter notification');
227
- switch (operation) {
228
- case 'NotificationNewsletterUpdate':
229
- for (const update of updates) {
230
- if (update.jid && update.settings && Object.keys(update.settings).length > 0) {
231
- ev.emit('newsletter-settings.update', {
232
- id: update.jid,
233
- update: update.settings
234
- });
235
- }
236
- }
237
- break;
238
- case 'NotificationNewsletterAdminPromote':
239
- for (const update of updates) {
240
- if (update.jid && update.user) {
241
- ev.emit('newsletter-participants.update', {
242
- id: update.jid,
243
- author: node.attrs.from,
244
- user: update.user,
245
- new_role: 'ADMIN',
246
- action: 'promote'
247
- });
248
- }
249
- }
250
- break;
251
- case 'NotificationLinkedProfilesUpdates':
252
- for (const update of updates) {
253
- const lid = update?.jid;
254
- const addedProfiles = Array.isArray(update?.added_profiles) ? update.added_profiles : [];
255
- const mappings = [];
256
- for (const profile of addedProfiles) {
257
- const pn = typeof profile === 'string' ? profile : (profile?.pn ?? profile?.jid ?? null);
258
- if (lid && pn) {
259
- const mapping = { lid, pn };
260
- ev.emit('lid-mapping.update', mapping);
261
- mappings.push(mapping);
262
- }
263
- }
264
- await signalRepository.lidMapping.storeLIDPNMappings(mappings);
265
- }
266
- break;
267
- default:
268
- logger.info({ operation, data }, 'unhandled mex newsletter notification');
269
- break;
270
- }
271
- };
272
- // Handles newsletter notifications
273
- const handleNewsletterNotification = async (node) => {
274
- const from = node.attrs.from;
275
- const children = getAllBinaryNodeChildren(node);
276
- const author = node.attrs.participant;
277
- for (const child of children) {
278
- logger.debug({ from, child }, 'got newsletter notification');
279
- switch (child.tag) {
280
- case 'reaction': {
281
- const reactionUpdate = {
282
- id: from,
283
- server_id: child.attrs.message_id,
284
- reaction: {
285
- code: getBinaryNodeChildString(child, 'reaction'),
286
- count: 1
287
- }
288
- };
289
- ev.emit('newsletter.reaction', reactionUpdate);
290
- break;
291
- }
292
- case 'view': {
293
- const viewUpdate = {
294
- id: from,
295
- server_id: child.attrs.message_id,
296
- count: parseInt(child.content?.toString() || '0', 10)
297
- };
298
- ev.emit('newsletter.view', viewUpdate);
299
- break;
300
- }
301
- case 'participant': {
302
- const participantUpdate = {
303
- id: from,
304
- author,
305
- user: child.attrs.jid,
306
- action: child.attrs.action,
307
- new_role: child.attrs.role
308
- };
309
- ev.emit('newsletter-participants.update', participantUpdate);
310
- break;
311
- }
312
- case 'update': {
313
- const settingsNode = getBinaryNodeChild(child, 'settings');
314
- if (settingsNode) {
315
- const update = {};
316
- const nameNode = getBinaryNodeChild(settingsNode, 'name');
317
- if (nameNode?.content)
318
- update.name = nameNode.content.toString();
319
- const descriptionNode = getBinaryNodeChild(settingsNode, 'description');
320
- if (descriptionNode?.content)
321
- update.description = descriptionNode.content.toString();
322
- ev.emit('newsletter-settings.update', {
323
- id: from,
324
- update
325
- });
326
- }
327
- break;
328
- }
329
- case 'message': {
330
- const plaintextNode = getBinaryNodeChild(child, 'plaintext');
331
- if (plaintextNode?.content) {
332
- try {
333
- const contentBuf = typeof plaintextNode.content === 'string'
334
- ? Buffer.from(plaintextNode.content, 'binary')
335
- : Buffer.from(plaintextNode.content);
336
- const messageProto = proto.Message.decode(contentBuf).toJSON();
337
- const fullMessage = proto.WebMessageInfo.fromObject({
338
- key: {
339
- remoteJid: from,
340
- id: child.attrs.message_id || child.attrs.server_id,
341
- fromMe: false // TODO: is this really true though
342
- },
343
- message: messageProto,
344
- messageTimestamp: +child.attrs.t
345
- }).toJSON();
346
- await upsertMessage(fullMessage, 'append');
347
- logger.debug('Processed plaintext newsletter message');
348
- }
349
- catch (error) {
350
- logger.error({ error }, 'Failed to decode plaintext newsletter message');
351
- }
352
- }
353
- break;
354
- }
355
- default:
356
- logger.warn({ node, child }, 'Unknown newsletter notification child');
357
- break;
358
- }
359
- }
360
- };
361
- const sendMessageAck = async (node, errorCode) => {
362
- const stanza = buildAckStanza(node, errorCode, authState.creds.me.id);
363
- logger.debug({ recv: { tag: node.tag, attrs: node.attrs }, sent: stanza.attrs }, 'sent ack');
364
- await sendNode(stanza);
110
+ await query(stanza);
111
+ return {
112
+ id: callId,
113
+ to: toJid
114
+ };
365
115
  };
366
116
  const rejectCall = async (callId, callFrom) => {
367
- const stanza = {
117
+ const stanza = ({
368
118
  tag: 'call',
369
119
  attrs: {
370
120
  from: authState.creds.me.id,
371
- to: callFrom
121
+ to: callFrom,
372
122
  },
373
- content: [
374
- {
123
+ content: [{
375
124
  tag: 'reject',
376
125
  attrs: {
377
126
  'call-id': callId,
378
127
  'call-creator': callFrom,
379
- count: '0'
128
+ count: '0',
380
129
  },
381
- content: undefined
382
- }
383
- ]
384
- };
130
+ content: undefined,
131
+ }],
132
+ });
385
133
  await query(stanza);
386
134
  };
387
135
  const sendRetryRequest = async (node, forceIncludeKeys = false) => {
388
- const { fullMessage } = decodeMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '');
136
+ const { fullMessage } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '');
389
137
  const { key: msgKey } = fullMessage;
390
138
  const msgId = msgKey.id;
391
- if (messageRetryManager) {
392
- // Check if we've exceeded max retries using the new system
393
- if (messageRetryManager.hasExceededMaxRetries(msgId)) {
394
- logger.debug({ msgId }, 'reached retry limit with new retry manager, clearing');
395
- messageRetryManager.markRetryFailed(msgId);
396
- return;
397
- }
398
- // Increment retry count using new system
399
- const retryCount = messageRetryManager.incrementRetryCount(msgId);
400
- // Use the new retry count for the rest of the logic
401
- const key = `${msgId}:${msgKey?.participant}`;
402
- await msgRetryCache.set(key, retryCount);
403
- }
404
- else {
405
- // Fallback to old system
406
- const key = `${msgId}:${msgKey?.participant}`;
407
- let retryCount = (await msgRetryCache.get(key)) || 0;
408
- if (retryCount >= maxMsgRetryCount) {
409
- logger.debug({ retryCount, msgId }, 'reached retry limit, clearing');
410
- await msgRetryCache.del(key);
411
- return;
412
- }
413
- retryCount += 1;
414
- await msgRetryCache.set(key, retryCount);
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;
415
145
  }
416
- const key = `${msgId}:${msgKey?.participant}`;
417
- const retryCount = (await msgRetryCache.get(key)) || 1;
146
+ retryCount += 1;
147
+ msgRetryCache.set(key, retryCount);
418
148
  const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds;
419
- const fromJid = node.attrs.from;
420
- // Check if we should recreate the session
421
- let shouldRecreateSession = false;
422
- let recreateReason = '';
423
- if (enableAutoSessionRecreation && messageRetryManager && retryCount > 1) {
424
- try {
425
- // Check if we have a session with this JID
426
- const sessionId = signalRepository.jidToSignalProtocolAddress(fromJid);
427
- const hasSession = await signalRepository.validateSession(fromJid);
428
- const result = messageRetryManager.shouldRecreateSession(fromJid, hasSession.exists);
429
- shouldRecreateSession = result.recreate;
430
- recreateReason = result.reason;
431
- if (shouldRecreateSession) {
432
- logger.debug({ fromJid, retryCount, reason: recreateReason }, 'recreating session for retry');
433
- // Delete existing session to force recreation
434
- await authState.keys.set({ session: { [sessionId]: null } });
435
- forceIncludeKeys = true;
436
- }
437
- }
438
- catch (error) {
439
- logger.warn({ error, fromJid }, 'failed to check session recreation');
440
- }
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}`);
441
153
  }
442
- if (retryCount <= 2) {
443
- // Use new retry manager for phone requests if available
444
- if (messageRetryManager) {
445
- // Schedule phone request with delay (like whatsmeow)
446
- messageRetryManager.schedulePhoneRequest(msgId, async () => {
447
- try {
448
- const requestId = await requestPlaceholderResend(msgKey);
449
- logger.debug(`sendRetryRequest: requested placeholder resend (${requestId}) for message ${msgId} (scheduled)`);
450
- }
451
- catch (error) {
452
- logger.warn({ error, msgId }, 'failed to send scheduled phone request');
453
- }
454
- });
455
- }
456
- else {
457
- // Fallback to immediate request
458
- const msgId = await requestPlaceholderResend(msgKey);
459
- logger.debug(`sendRetryRequest: requested placeholder resend for message ${msgId}`);
460
- }
461
- }
462
- const deviceIdentity = encodeSignedDeviceIdentity(account, true);
154
+ const deviceIdentity = (0, Utils_1.encodeSignedDeviceIdentity)(account, true);
463
155
  await authState.keys.transaction(async () => {
464
156
  const receipt = {
465
157
  tag: 'receipt',
@@ -475,15 +167,13 @@ export const makeMessagesRecvSocket = (config) => {
475
167
  count: retryCount.toString(),
476
168
  id: node.attrs.id,
477
169
  t: node.attrs.t,
478
- v: '1',
479
- // ADD ERROR FIELD
480
- error: '0'
170
+ v: '1'
481
171
  }
482
172
  },
483
173
  {
484
174
  tag: 'registration',
485
175
  attrs: {},
486
- content: encodeBigEndian(authState.creds.registrationId)
176
+ content: (0, Utils_1.encodeBigEndian)(authState.creds.registrationId)
487
177
  }
488
178
  ]
489
179
  };
@@ -493,8 +183,8 @@ export const makeMessagesRecvSocket = (config) => {
493
183
  if (node.attrs.participant) {
494
184
  receipt.attrs.participant = node.attrs.participant;
495
185
  }
496
- if (retryCount > 1 || forceIncludeKeys || shouldRecreateSession) {
497
- const { update, preKeys } = await getNextPreKeys(authState, 1);
186
+ if (retryCount > 1 || forceIncludeKeys) {
187
+ const { update, preKeys } = await (0, Utils_1.getNextPreKeys)(authState, 1);
498
188
  const [keyId] = Object.keys(preKeys);
499
189
  const key = preKeys[+keyId];
500
190
  const content = receipt.content;
@@ -502,10 +192,10 @@ export const makeMessagesRecvSocket = (config) => {
502
192
  tag: 'keys',
503
193
  attrs: {},
504
194
  content: [
505
- { tag: 'type', attrs: {}, content: Buffer.from(KEY_BUNDLE_TYPE) },
195
+ { tag: 'type', attrs: {}, content: Buffer.from(Defaults_1.KEY_BUNDLE_TYPE) },
506
196
  { tag: 'identity', attrs: {}, content: identityKey.public },
507
- xmppPreKey(key, +keyId),
508
- xmppSignedPreKey(signedPreKey),
197
+ (0, Utils_1.xmppPreKey)(key, +keyId),
198
+ (0, Utils_1.xmppSignedPreKey)(signedPreKey),
509
199
  { tag: 'device-identity', attrs: {}, content: deviceIdentity }
510
200
  ]
511
201
  });
@@ -513,119 +203,63 @@ export const makeMessagesRecvSocket = (config) => {
513
203
  }
514
204
  await sendNode(receipt);
515
205
  logger.info({ msgAttrs: node.attrs, retryCount }, 'sent retry receipt');
516
- }, authState?.creds?.me?.id || 'sendRetryRequest');
517
- };
518
- // Mirrors WAWeb/Handle/PreKeyLow.js: skip a re-issued notification with the same stanza id.
519
- const inFlightPreKeyLow = new Set();
520
- /**
521
- * Fire-and-forget tctoken re-issuance after a peer's device identity changed.
522
- * Mirrors WAWebSendTcTokenWhenDeviceIdentityChange — runs in parallel with
523
- * the session refresh (not after it).
524
- */
525
- const reissueTcTokenAfterIdentityChange = (from) => {
526
- void (async () => {
527
- const normalizedJid = jidNormalizedUser(from);
528
- const tcJid = await resolveTcTokenJid(normalizedJid, getLIDForPN);
529
- const tcTokenData = await authState.keys.get('tctoken', [tcJid]);
530
- const senderTs = tcTokenData?.[tcJid]?.senderTimestamp;
531
- if (senderTs === null || senderTs === undefined || isTcTokenExpired(senderTs)) {
532
- return;
533
- }
534
- logger.debug({ jid: normalizedJid, senderTimestamp: senderTs }, 'identity changed, re-issuing tctoken');
535
- const getPNForLID = signalRepository.lidMapping.getPNForLID.bind(signalRepository.lidMapping);
536
- const issueJid = await resolveIssuanceJid(normalizedJid, sock.serverProps.lidTrustedTokenIssueToLid, getLIDForPN, getPNForLID);
537
- const result = await issuePrivacyTokens([issueJid], senderTs);
538
- await storeTcTokensFromIqResult({
539
- result,
540
- fallbackJid: tcJid,
541
- keys: authState.keys,
542
- getLIDForPN,
543
- onNewJidStored: trackTcTokenJid
544
- });
545
- })().catch(err => {
546
- logger.debug({ jid: from, err: err?.message }, 'failed to re-issue tctoken after identity change');
547
206
  });
548
207
  };
549
208
  const handleEncryptNotification = async (node) => {
550
209
  const from = node.attrs.from;
551
- if (from === S_WHATSAPP_NET) {
552
- const stanzaId = node.attrs.id;
553
- if (stanzaId && inFlightPreKeyLow.has(stanzaId)) {
554
- return;
555
- }
556
- const countChild = getBinaryNodeChild(node, 'count');
210
+ if (from === WABinary_1.S_WHATSAPP_NET) {
211
+ const countChild = (0, WABinary_1.getBinaryNodeChild)(node, 'count');
557
212
  const count = +countChild.attrs.value;
558
- const shouldUploadMorePreKeys = count < MIN_PREKEY_COUNT;
213
+ const shouldUploadMorePreKeys = count < Defaults_1.MIN_PREKEY_COUNT;
559
214
  logger.debug({ count, shouldUploadMorePreKeys }, 'recv pre-key count');
560
215
  if (shouldUploadMorePreKeys) {
561
- if (stanzaId)
562
- inFlightPreKeyLow.add(stanzaId);
563
- try {
564
- await uploadPreKeys();
565
- }
566
- finally {
567
- if (stanzaId)
568
- inFlightPreKeyLow.delete(stanzaId);
569
- }
216
+ await uploadPreKeys();
570
217
  }
571
218
  }
572
219
  else {
573
- const result = await handleIdentityChange(node, {
574
- meId: authState.creds.me?.id,
575
- meLid: authState.creds.me?.lid,
576
- validateSession: signalRepository.validateSession,
577
- assertSessions,
578
- debounceCache: identityAssertDebounce,
579
- logger,
580
- onBeforeSessionRefresh: reissueTcTokenAfterIdentityChange
581
- });
582
- if (result.action === 'no_identity_node') {
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 {
583
227
  logger.info({ node }, 'unknown encrypt notification');
584
228
  }
585
229
  }
586
230
  };
587
- const handleGroupNotification = (fullNode, child, msg) => {
588
- // TODO: Support PN/LID (Here is only LID now)
589
- const actingParticipantLid = fullNode.attrs.participant;
590
- const actingParticipantPn = fullNode.attrs.participant_pn;
591
- const actingParticipantUsername = fullNode.attrs.participant_username;
592
- const affectedParticipantLid = getBinaryNodeChild(child, 'participant')?.attrs?.jid || actingParticipantLid;
593
- const affectedParticipantPn = getBinaryNodeChild(child, 'participant')?.attrs?.phone_number || actingParticipantPn;
594
- switch (child?.tag) {
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) {
595
235
  case 'create':
596
- const metadata = extractGroupMetadata(child);
597
- msg.messageStubType = WAMessageStubType.GROUP_CREATE;
236
+ const metadata = (0, groups_1.extractGroupMetadata)(child);
237
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_CREATE;
598
238
  msg.messageStubParameters = [metadata.subject];
599
- msg.key = { participant: metadata.owner, participantAlt: metadata.ownerPn };
600
- ev.emit('chats.upsert', [
601
- {
239
+ msg.key = { participant: metadata.owner };
240
+ ev.emit('chats.upsert', [{
602
241
  id: metadata.id,
603
242
  name: metadata.subject,
604
- conversationTimestamp: metadata.creation
605
- }
606
- ]);
607
- ev.emit('groups.upsert', [
608
- {
243
+ conversationTimestamp: metadata.creation,
244
+ }]);
245
+ ev.emit('groups.upsert', [{
609
246
  ...metadata,
610
- author: actingParticipantLid,
611
- authorPn: actingParticipantPn,
612
- authorUsername: actingParticipantUsername
613
- }
614
- ]);
247
+ author: participant
248
+ }]);
615
249
  break;
616
250
  case 'ephemeral':
617
251
  case 'not_ephemeral':
618
252
  msg.message = {
619
253
  protocolMessage: {
620
- type: proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
254
+ type: WAProto_1.proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
621
255
  ephemeralExpiration: +(child.attrs.expiration || 0)
622
256
  }
623
257
  };
624
258
  break;
625
259
  case 'modify':
626
- const oldNumber = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid);
260
+ const oldNumber = (0, WABinary_1.getBinaryNodeChildren)(child, 'participant').map(p => p.attrs.jid);
627
261
  msg.messageStubParameters = oldNumber || [];
628
- msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
262
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
629
263
  break;
630
264
  case 'promote':
631
265
  case 'demote':
@@ -633,224 +267,126 @@ export const makeMessagesRecvSocket = (config) => {
633
267
  case 'add':
634
268
  case 'leave':
635
269
  const stubType = `GROUP_PARTICIPANT_${child.tag.toUpperCase()}`;
636
- msg.messageStubType = WAMessageStubType[stubType];
637
- const participants = getBinaryNodeChildren(child, 'participant').map(({ attrs }) => {
638
- // TODO: Store LID MAPPINGS
639
- return {
640
- id: attrs.jid,
641
- phoneNumber: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined,
642
- lid: isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined,
643
- username: attrs.participant_username || attrs.username || undefined,
644
- admin: (attrs.type || null)
645
- };
646
- });
270
+ msg.messageStubType = Types_1.WAMessageStubType[stubType];
271
+ const participants = (0, WABinary_1.getBinaryNodeChildren)(child, 'participant').map(p => p.attrs.jid);
647
272
  if (participants.length === 1 &&
648
273
  // if recv. "remove" message and sender removed themselves
649
274
  // mark as left
650
- (areJidsSameUser(participants[0].id, actingParticipantLid) ||
651
- areJidsSameUser(participants[0].id, actingParticipantPn)) &&
275
+ (0, WABinary_1.areJidsSameUser)(participants[0], participant) &&
652
276
  child.tag === 'remove') {
653
- msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_LEAVE;
277
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_PARTICIPANT_LEAVE;
654
278
  }
655
- msg.messageStubParameters = participants.map(a => JSON.stringify(a));
279
+ msg.messageStubParameters = participants;
656
280
  break;
657
281
  case 'subject':
658
- msg.messageStubType = WAMessageStubType.GROUP_CHANGE_SUBJECT;
282
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_SUBJECT;
659
283
  msg.messageStubParameters = [child.attrs.subject];
660
284
  break;
661
285
  case 'description':
662
- const description = getBinaryNodeChild(child, 'body')?.content?.toString();
663
- msg.messageStubType = WAMessageStubType.GROUP_CHANGE_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;
664
288
  msg.messageStubParameters = description ? [description] : undefined;
665
289
  break;
666
290
  case 'announcement':
667
291
  case 'not_announcement':
668
- msg.messageStubType = WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
669
- msg.messageStubParameters = [child.tag === 'announcement' ? 'on' : 'off'];
292
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
293
+ msg.messageStubParameters = [(child.tag === 'announcement') ? 'on' : 'off'];
670
294
  break;
671
295
  case 'locked':
672
296
  case 'unlocked':
673
- msg.messageStubType = WAMessageStubType.GROUP_CHANGE_RESTRICT;
674
- msg.messageStubParameters = [child.tag === 'locked' ? 'on' : 'off'];
297
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_RESTRICT;
298
+ msg.messageStubParameters = [(child.tag === 'locked') ? 'on' : 'off'];
675
299
  break;
676
300
  case 'invite':
677
- msg.messageStubType = WAMessageStubType.GROUP_CHANGE_INVITE_LINK;
301
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_INVITE_LINK;
678
302
  msg.messageStubParameters = [child.attrs.code];
679
303
  break;
680
304
  case 'member_add_mode':
681
305
  const addMode = child.content;
682
306
  if (addMode) {
683
- msg.messageStubType = WAMessageStubType.GROUP_MEMBER_ADD_MODE;
307
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBER_ADD_MODE;
684
308
  msg.messageStubParameters = [addMode.toString()];
685
309
  }
686
310
  break;
687
311
  case 'membership_approval_mode':
688
- const approvalMode = getBinaryNodeChild(child, 'group_join');
312
+ const approvalMode = (0, WABinary_1.getBinaryNodeChild)(child, 'group_join');
689
313
  if (approvalMode) {
690
- msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE;
314
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE;
691
315
  msg.messageStubParameters = [approvalMode.attrs.state];
692
316
  }
693
317
  break;
694
318
  case 'created_membership_requests':
695
- msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
696
- msg.messageStubParameters = [
697
- JSON.stringify({ lid: affectedParticipantLid, pn: affectedParticipantPn }),
698
- 'created',
699
- child.attrs.request_method
700
- ];
319
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
320
+ msg.messageStubParameters = [participantJid, 'created', child.attrs.request_method];
701
321
  break;
702
322
  case 'revoked_membership_requests':
703
- const isDenied = areJidsSameUser(affectedParticipantLid, actingParticipantLid);
704
- // TODO: LIDMAPPING SUPPORT
705
- msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
706
- msg.messageStubParameters = [
707
- JSON.stringify({ lid: affectedParticipantLid, pn: affectedParticipantPn }),
708
- isDenied ? 'revoked' : 'rejected'
709
- ];
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'];
710
326
  break;
711
327
  }
712
328
  };
713
- const handleDevicesNotification = async (node) => {
714
- const [child] = getAllBinaryNodeChildren(node);
715
- const from = jidNormalizedUser(node.attrs.from);
716
- if (!child) {
717
- logger.debug({ from }, 'devices notification missing child, skipping');
718
- return;
719
- }
720
- const tag = child.tag;
721
- const deviceHash = child.attrs.device_hash;
722
- const devices = getBinaryNodeChildren(child, 'device');
723
- if (areJidsSameUser(from, authState.creds.me.id) || areJidsSameUser(from, authState.creds.me.lid)) {
724
- const deviceJids = devices.map(d => d.attrs.jid);
725
- logger.info({ deviceJids }, 'got my own devices');
726
- }
727
- if (!devices.length) {
728
- logger.debug({ from, tag }, 'no devices in notification, skipping');
729
- return;
730
- }
731
- const decoded = [];
732
- for (const d of devices) {
733
- const jid = d.attrs.jid;
734
- if (!jid)
735
- continue;
736
- const parts = jidDecode(jid);
737
- if (!parts) {
738
- logger.debug({ jid }, 'failed to decode device jid, skipping');
739
- continue;
740
- }
741
- decoded.push({ jid, user: parts.user, server: parts.server, device: parts.device });
742
- }
743
- if (!decoded.length)
744
- return;
745
- await devicesMutex.mutex(async () => {
746
- const byUser = new Map();
747
- for (const d of decoded) {
748
- const list = byUser.get(d.user) || [];
749
- list.push(d);
750
- byUser.set(d.user, list);
751
- }
752
- for (const [user, entries] of byUser) {
753
- if (tag === 'update') {
754
- logger.debug({ user }, `${user}'s device list updated, dropping cached devices`);
755
- await userDevicesCache?.del(user);
756
- continue;
757
- }
758
- if (tag === 'remove') {
759
- await signalRepository.deleteSession(entries.map(e => e.jid));
760
- }
761
- const existingCache = (await userDevicesCache?.get(user)) || [];
762
- if (!existingCache.length) {
763
- // No baseline yet; skip applying the delta so getUSyncDevices can
764
- // later fetch the full device list. Caching just the notification
765
- // entries would make a partial list look authoritative.
766
- logger.debug({ user, tag }, 'device list not cached, deferring to USync refresh');
767
- continue;
768
- }
769
- const affected = new Set(entries.map(e => e.device));
770
- let updatedDevices;
771
- switch (tag) {
772
- case 'add':
773
- logger.info({ deviceHash, count: entries.length }, 'devices added');
774
- updatedDevices = [
775
- ...existingCache.filter(d => !affected.has(d.device)),
776
- ...entries.map(e => ({ user: e.user, server: e.server, device: e.device }))
777
- ];
778
- break;
779
- case 'remove':
780
- logger.info({ deviceHash, count: entries.length }, 'devices removed');
781
- updatedDevices = existingCache.filter(d => !affected.has(d.device));
782
- break;
783
- default:
784
- logger.debug({ tag }, 'Unknown device list change tag');
785
- continue;
786
- }
787
- if (updatedDevices.length === 0) {
788
- await userDevicesCache?.del(user);
789
- }
790
- else {
791
- await userDevicesCache?.set(user, updatedDevices);
792
- }
793
- }
794
- });
795
- };
796
329
  const processNotification = async (node) => {
330
+ var _a, _b, _c;
797
331
  const result = {};
798
- const [child] = getAllBinaryNodeChildren(node);
332
+ const [child] = (0, WABinary_1.getAllBinaryNodeChildren)(node);
799
333
  const nodeType = node.attrs.type;
800
- const from = jidNormalizedUser(node.attrs.from);
334
+ const from = (0, WABinary_1.jidNormalizedUser)(node.attrs.from);
801
335
  switch (nodeType) {
802
- case 'newsletter':
803
- await handleNewsletterNotification(node);
804
- break;
805
- case 'mex':
806
- await handleMexNotification(node);
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
+ }
807
348
  break;
808
349
  case 'w:gp2':
809
- // TODO: HANDLE PARTICIPANT_PN
810
- handleGroupNotification(node, child, result);
350
+ handleGroupNotification(node.attrs.participant, child, result);
811
351
  break;
812
352
  case 'mediaretry':
813
- const event = decodeMediaRetryNode(node);
353
+ const event = (0, Utils_1.decodeMediaRetryNode)(node);
814
354
  ev.emit('messages.media-update', [event]);
815
355
  break;
816
356
  case 'encrypt':
817
357
  await handleEncryptNotification(node);
818
358
  break;
819
359
  case 'devices':
820
- try {
821
- await handleDevicesNotification(node);
822
- }
823
- catch (error) {
824
- logger.error({ error, node }, 'failed to handle devices notification');
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');
825
364
  }
826
365
  break;
827
366
  case 'server_sync':
828
- const update = getBinaryNodeChild(node, 'collection');
367
+ const update = (0, WABinary_1.getBinaryNodeChild)(node, 'collection');
829
368
  if (update) {
830
369
  const name = update.attrs.name;
831
370
  await resyncAppState([name], false);
832
371
  }
833
372
  break;
834
373
  case 'picture':
835
- const setPicture = getBinaryNodeChild(node, 'set');
836
- const delPicture = getBinaryNodeChild(node, 'delete');
837
- // TODO: WAJIDHASH stuff proper support inhouse
838
- ev.emit('contacts.update', [
839
- {
840
- id: jidNormalizedUser(node?.attrs?.from) || (setPicture || delPicture)?.attrs?.hash || '',
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) || '',
841
378
  imgUrl: setPicture ? 'changed' : 'removed'
842
- }
843
- ]);
844
- if (isJidGroup(from)) {
379
+ }]);
380
+ if ((0, WABinary_1.isJidGroup)(from)) {
845
381
  const node = setPicture || delPicture;
846
- result.messageStubType = WAMessageStubType.GROUP_CHANGE_ICON;
382
+ result.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_ICON;
847
383
  if (setPicture) {
848
384
  result.messageStubParameters = [setPicture.attrs.id];
849
385
  }
850
- result.participant = node?.attrs.author;
386
+ result.participant = node === null || node === void 0 ? void 0 : node.attrs.author;
851
387
  result.key = {
852
- ...(result.key || {}),
853
- participant: setPicture?.attrs.author
388
+ ...result.key || {},
389
+ participant: setPicture === null || setPicture === void 0 ? void 0 : setPicture.attrs.author
854
390
  };
855
391
  }
856
392
  break;
@@ -864,48 +400,44 @@ export const makeMessagesRecvSocket = (config) => {
864
400
  ...authState.creds.accountSettings,
865
401
  defaultDisappearingMode: {
866
402
  ephemeralExpiration: newDuration,
867
- ephemeralSettingTimestamp: timestamp
868
- }
403
+ ephemeralSettingTimestamp: timestamp,
404
+ },
869
405
  }
870
406
  });
871
407
  }
872
408
  else if (child.tag === 'blocklist') {
873
- const blocklists = getBinaryNodeChildren(child, 'item');
409
+ const blocklists = (0, WABinary_1.getBinaryNodeChildren)(child, 'item');
874
410
  for (const { attrs } of blocklists) {
875
411
  const blocklist = [attrs.jid];
876
- const type = attrs.action === 'block' ? 'add' : 'remove';
412
+ const type = (attrs.action === 'block') ? 'add' : 'remove';
877
413
  ev.emit('blocklist.update', { blocklist, type });
878
414
  }
879
415
  }
880
416
  break;
881
417
  case 'link_code_companion_reg':
882
- const linkCodeCompanionReg = getBinaryNodeChild(node, 'link_code_companion_reg');
883
- const ref = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_ref'));
884
- const primaryIdentityPublicKey = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'primary_identity_pub'));
885
- const primaryEphemeralPublicKeyWrapped = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_wrapped_primary_ephemeral_pub'));
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'));
886
422
  const codePairingPublicKey = await decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
887
- const companionSharedKey = Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey);
888
- const random = randomBytes(32);
889
- const linkCodeSalt = randomBytes(32);
890
- const linkCodePairingExpanded = hkdf(companionSharedKey, 32, {
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, {
891
427
  salt: linkCodeSalt,
892
428
  info: 'link_code_pairing_key_bundle_encryption_key'
893
429
  });
894
- const encryptPayload = Buffer.concat([
895
- Buffer.from(authState.creds.signedIdentityKey.public),
896
- primaryIdentityPublicKey,
897
- random
898
- ]);
899
- const encryptIv = randomBytes(12);
900
- const encrypted = aesEncryptGCM(encryptPayload, linkCodePairingExpanded, encryptIv, Buffer.alloc(0));
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));
901
433
  const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted]);
902
- const identitySharedKey = Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey);
434
+ const identitySharedKey = Utils_1.Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey);
903
435
  const identityPayload = Buffer.concat([companionSharedKey, identitySharedKey, random]);
904
- authState.creds.advSecretKey = Buffer.from(hkdf(identityPayload, 32, { info: 'adv_secret' })).toString('base64');
436
+ authState.creds.advSecretKey = (await (0, Utils_1.hkdf)(identityPayload, 32, { info: 'adv_secret' })).toString('base64');
905
437
  await query({
906
438
  tag: 'iq',
907
439
  attrs: {
908
- to: S_WHATSAPP_NET,
440
+ to: WABinary_1.S_WHATSAPP_NET,
909
441
  type: 'set',
910
442
  id: sock.generateMessageTag(),
911
443
  xmlns: 'md'
@@ -915,7 +447,7 @@ export const makeMessagesRecvSocket = (config) => {
915
447
  tag: 'link_code_companion_reg',
916
448
  attrs: {
917
449
  jid: authState.creds.me.id,
918
- stage: 'companion_finish'
450
+ stage: 'companion_finish',
919
451
  },
920
452
  content: [
921
453
  {
@@ -939,208 +471,52 @@ export const makeMessagesRecvSocket = (config) => {
939
471
  });
940
472
  authState.creds.registered = true;
941
473
  ev.emit('creds.update', authState.creds);
942
- break;
943
- case 'privacy_token':
944
- await handlePrivacyTokenNotification(node);
945
- break;
946
474
  }
947
475
  if (Object.keys(result).length) {
948
476
  return result;
949
477
  }
950
478
  };
951
- /**
952
- * In-memory cache of storage JIDs with stored tctokens, seeded from the persisted index.
953
- * Used to coalesce writes during a session; pruning always re-reads the persisted index
954
- * to cover writes made by other layers (e.g. history sync).
955
- */
956
- const tcTokenKnownJids = new Set();
957
- const tcTokenIndexLoaded = (async () => {
958
- try {
959
- const jids = await readTcTokenIndex(authState.keys);
960
- for (const jid of jids)
961
- tcTokenKnownJids.add(jid);
962
- logger.debug({ count: tcTokenKnownJids.size }, 'loaded tctoken index');
963
- }
964
- catch (err) {
965
- logger.warn({ err: err?.message }, 'failed to load tctoken index');
966
- }
967
- })();
968
- let tcTokenIndexTimer;
969
- async function flushTcTokenIndex() {
970
- if (tcTokenIndexTimer) {
971
- clearTimeout(tcTokenIndexTimer);
972
- tcTokenIndexTimer = undefined;
973
- }
974
- // Merge with whatever is already persisted so we don't clobber writes from other
975
- // paths (history sync, concurrent sessions on the same store).
976
- const write = await buildMergedTcTokenIndexWrite(authState.keys, tcTokenKnownJids);
977
- return authState.keys.set({ tctoken: write });
978
- }
979
- function scheduleTcTokenIndexSave() {
980
- if (tcTokenIndexTimer) {
981
- clearTimeout(tcTokenIndexTimer);
982
- }
983
- tcTokenIndexTimer = setTimeout(() => {
984
- tcTokenIndexTimer = undefined;
985
- flushTcTokenIndex().catch(err => {
986
- logger.warn({ err: err?.message }, 'failed to save tctoken index');
987
- });
988
- }, 5000);
989
- }
990
- function trackTcTokenJid(jid) {
991
- if (jid && jid !== TC_TOKEN_INDEX_KEY && !tcTokenKnownJids.has(jid)) {
992
- tcTokenKnownJids.add(jid);
993
- scheduleTcTokenIndexSave();
994
- }
995
- }
996
- const handlePrivacyTokenNotification = async (node) => {
997
- const tokensNode = getBinaryNodeChild(node, 'tokens');
998
- if (!tokensNode)
999
- return;
1000
- const from = jidNormalizedUser(node.attrs.from);
1001
- // WA Web uses: senderLid ?? toLid(from) for the storage key
1002
- // The sender_lid attribute provides the LID directly when available
1003
- const senderLid = node.attrs.sender_lid && isLidUser(jidNormalizedUser(node.attrs.sender_lid))
1004
- ? jidNormalizedUser(node.attrs.sender_lid)
1005
- : undefined;
1006
- const fallbackJid = senderLid ?? (await resolveTcTokenJid(from, getLIDForPN));
1007
- logger.debug({ from, storageJid: fallbackJid }, 'processing privacy token notification');
1008
- await storeTcTokensFromIqResult({
1009
- result: node,
1010
- fallbackJid,
1011
- keys: authState.keys,
1012
- getLIDForPN,
1013
- onNewJidStored: trackTcTokenJid
1014
- });
1015
- };
1016
479
  async function decipherLinkPublicKey(data) {
1017
480
  const buffer = toRequiredBuffer(data);
1018
481
  const salt = buffer.slice(0, 32);
1019
- const secretKey = await derivePairingCodeKey(authState.creds.pairingCode, salt);
482
+ const secretKey = await (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
1020
483
  const iv = buffer.slice(32, 48);
1021
484
  const payload = buffer.slice(48, 80);
1022
- return aesDecryptCTR(payload, secretKey, iv);
485
+ return (0, Utils_1.aesDecryptCTR)(payload, secretKey, iv);
1023
486
  }
1024
487
  function toRequiredBuffer(data) {
1025
488
  if (data === undefined) {
1026
- throw new Boom('Invalid buffer', { statusCode: 400 });
489
+ throw new boom_1.Boom('Invalid buffer', { statusCode: 400 });
1027
490
  }
1028
491
  return data instanceof Buffer ? data : Buffer.from(data);
1029
492
  }
1030
- const willSendMessageAgain = async (id, participant) => {
493
+ const willSendMessageAgain = (id, participant) => {
1031
494
  const key = `${id}:${participant}`;
1032
- const retryCount = (await msgRetryCache.get(key)) || 0;
495
+ const retryCount = msgRetryCache.get(key) || 0;
1033
496
  return retryCount < maxMsgRetryCount;
1034
497
  };
1035
- const updateSendMessageAgainCount = async (id, participant) => {
498
+ const updateSendMessageAgainCount = (id, participant) => {
1036
499
  const key = `${id}:${participant}`;
1037
- const newValue = ((await msgRetryCache.get(key)) || 0) + 1;
1038
- await msgRetryCache.set(key, newValue);
500
+ const newValue = (msgRetryCache.get(key) || 0) + 1;
501
+ msgRetryCache.set(key, newValue);
1039
502
  };
1040
- const sendMessagesAgain = async (key, ids, retryNode, receiptNode) => {
503
+ const sendMessagesAgain = async (key, ids, retryNode) => {
504
+ var _a;
505
+ const msgs = await Promise.all(ids.map(id => getMessage({ ...key, id })));
1041
506
  const remoteJid = key.remoteJid;
1042
507
  const participant = key.participant || remoteJid;
1043
- const retryCount = +retryNode.attrs.count || 1;
1044
- const msgId = ids[0];
1045
- // Try to get messages from cache first, then fallback to getMessage
1046
- const msgs = [];
1047
- for (const id of ids) {
1048
- let msg;
1049
- // Try to get from retry cache first if enabled
1050
- if (messageRetryManager) {
1051
- const cachedMsg = messageRetryManager.getRecentMessage(remoteJid, id);
1052
- if (cachedMsg) {
1053
- msg = cachedMsg.message;
1054
- logger.debug({ jid: remoteJid, id }, 'found message in retry cache');
1055
- // Mark retry as successful since we found the message
1056
- messageRetryManager.markRetrySuccess(id);
1057
- }
1058
- }
1059
- // Fallback to getMessage if not found in cache
1060
- if (!msg) {
1061
- msg = await getMessage({ ...key, id });
1062
- if (msg) {
1063
- logger.debug({ jid: remoteJid, id }, 'found message via getMessage');
1064
- // Also mark as successful if found via getMessage
1065
- if (messageRetryManager) {
1066
- messageRetryManager.markRetrySuccess(id);
1067
- }
1068
- }
1069
- }
1070
- msgs.push(msg);
1071
- }
1072
508
  // if it's the primary jid sending the request
1073
509
  // just re-send the message to everyone
1074
510
  // prevents the first message decryption failure
1075
- const sendToAll = !jidDecode(participant)?.device;
1076
- const sessionId = signalRepository.jidToSignalProtocolAddress(participant);
1077
- let injectedFromBundle = false;
1078
- const bundle = extractE2ESessionFromRetryReceipt(receiptNode);
1079
- if (bundle) {
1080
- try {
1081
- await signalRepository.injectE2ESession({ jid: participant, session: bundle });
1082
- injectedFromBundle = true;
1083
- logger.debug({ participant, retryCount }, 'injected session from retry receipt key bundle');
1084
- }
1085
- catch (error) {
1086
- logger.warn({ error, participant }, 'failed to inject session from retry receipt');
1087
- }
1088
- }
1089
- if (!injectedFromBundle) {
1090
- const receivedRegId = getBinaryNodeChildUInt(receiptNode, 'registration', 4);
1091
- if (typeof receivedRegId === 'number' && Number.isInteger(receivedRegId)) {
1092
- const info = await signalRepository.getSessionInfo(participant);
1093
- if (info && info.registrationId !== 0 && info.registrationId !== receivedRegId) {
1094
- logger.info({ participant, stored: info.registrationId, received: receivedRegId }, 'reg id mismatch on retry without bundle, deleting session');
1095
- await authState.keys.set({ session: { [sessionId]: null } });
1096
- }
1097
- }
1098
- }
1099
- const BASE_KEY_CHECK_RETRY = 2;
1100
- if (msgId && messageRetryManager) {
1101
- const info = await signalRepository.getSessionInfo(participant);
1102
- if (info) {
1103
- if (retryCount === BASE_KEY_CHECK_RETRY) {
1104
- messageRetryManager.saveBaseKey(sessionId, msgId, info.baseKey);
1105
- }
1106
- else if (retryCount > BASE_KEY_CHECK_RETRY) {
1107
- if (messageRetryManager.hasSameBaseKey(sessionId, msgId, info.baseKey)) {
1108
- logger.warn({ participant, retryCount }, 'base key collision on retry, forcing fresh session');
1109
- await authState.keys.set({ session: { [sessionId]: null } });
1110
- }
1111
- messageRetryManager.deleteBaseKey(sessionId, msgId);
1112
- }
1113
- }
1114
- }
1115
- let shouldRecreateSession = false;
1116
- let recreateReason = '';
1117
- if (enableAutoSessionRecreation && messageRetryManager && retryCount > 1 && !injectedFromBundle) {
1118
- try {
1119
- const hasSession = await signalRepository.validateSession(participant);
1120
- const result = messageRetryManager.shouldRecreateSession(participant, hasSession.exists);
1121
- shouldRecreateSession = result.recreate;
1122
- recreateReason = result.reason;
1123
- if (shouldRecreateSession) {
1124
- logger.debug({ participant, retryCount, reason: recreateReason }, 'recreating session for outgoing retry');
1125
- await authState.keys.set({ session: { [sessionId]: null } });
1126
- }
1127
- }
1128
- catch (error) {
1129
- logger.warn({ error, participant }, 'failed to check session recreation for outgoing retry');
1130
- }
1131
- }
1132
- if (!injectedFromBundle) {
1133
- await assertSessions([participant], true);
1134
- }
1135
- if (isJidGroup(remoteJid)) {
511
+ const sendToAll = !((_a = (0, WABinary_1.jidDecode)(participant)) === null || _a === void 0 ? void 0 : _a.device);
512
+ await assertSessions([participant], true);
513
+ if ((0, WABinary_1.isJidGroup)(remoteJid)) {
1136
514
  await authState.keys.set({ 'sender-key-memory': { [remoteJid]: null } });
1137
515
  }
1138
- logger.debug({ participant, sendToAll, shouldRecreateSession, recreateReason, injectedFromBundle }, 'prepared session for retry resend');
516
+ logger.debug({ participant, sendToAll }, 'forced new session for retry recp');
1139
517
  for (const [i, msg] of msgs.entries()) {
1140
- if (!ids[i])
1141
- continue;
1142
- if (msg && (await willSendMessageAgain(ids[i], participant))) {
1143
- await updateSendMessageAgainCount(ids[i], participant);
518
+ if (msg) {
519
+ updateSendMessageAgainCount(ids[i], participant);
1144
520
  const msgRelayOpts = { messageId: ids[i] };
1145
521
  if (sendToAll) {
1146
522
  msgRelayOpts.useUserDevicesCache = false;
@@ -1159,37 +535,45 @@ export const makeMessagesRecvSocket = (config) => {
1159
535
  }
1160
536
  };
1161
537
  const handleReceipt = async (node) => {
538
+ var _a, _b;
1162
539
  const { attrs, content } = node;
1163
540
  const isLid = attrs.from.includes('lid');
1164
- const isNodeFromMe = areJidsSameUser(attrs.participant || attrs.from, isLid ? authState.creds.me?.lid : authState.creds.me?.id);
1165
- const remoteJid = !isNodeFromMe || isJidGroup(attrs.from) ? attrs.from : attrs.recipient;
1166
- const fromMe = !attrs.recipient || ((attrs.type === 'retry' || attrs.type === 'sender') && isNodeFromMe);
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);
1167
544
  const key = {
1168
545
  remoteJid,
1169
546
  id: '',
1170
547
  fromMe,
1171
548
  participant: attrs.participant
1172
549
  };
550
+ if (shouldIgnoreJid(remoteJid) && remoteJid !== '@s.whatsapp.net') {
551
+ logger.debug({ remoteJid }, 'ignoring receipt from jid');
552
+ await sendMessageAck(node);
553
+ return;
554
+ }
1173
555
  const ids = [attrs.id];
1174
556
  if (Array.isArray(content)) {
1175
- const items = getBinaryNodeChildren(content[0], 'item');
557
+ const items = (0, WABinary_1.getBinaryNodeChildren)(content[0], 'item');
1176
558
  ids.push(...items.map(i => i.attrs.id));
1177
559
  }
1178
560
  try {
1179
561
  await Promise.all([
1180
- receiptMutex.mutex(async () => {
1181
- const status = getStatusFromReceiptType(attrs.type);
562
+ processingMutex.mutex(async () => {
563
+ const status = (0, Utils_1.getStatusFromReceiptType)(attrs.type);
1182
564
  if (typeof status !== 'undefined' &&
565
+ (
1183
566
  // basically, we only want to know when a message from us has been delivered to/read by the other person
1184
567
  // or another device of ours has read some messages
1185
- (status >= proto.WebMessageInfo.Status.SERVER_ACK || !isNodeFromMe)) {
1186
- if (isJidGroup(remoteJid) || isJidStatusBroadcast(remoteJid)) {
568
+ status >= WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ||
569
+ !isNodeFromMe)) {
570
+ if ((0, WABinary_1.isJidGroup)(remoteJid) || (0, WABinary_1.isJidStatusBroadcast)(remoteJid)) {
1187
571
  if (attrs.participant) {
1188
- const updateKey = status === proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
572
+ const updateKey = status === WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
1189
573
  ev.emit('message-receipt.update', ids.map(id => ({
1190
574
  key: { ...key, id },
1191
575
  receipt: {
1192
- userJid: jidNormalizedUser(attrs.participant),
576
+ userJid: (0, WABinary_1.jidNormalizedUser)(attrs.participant),
1193
577
  [updateKey]: +attrs.t
1194
578
  }
1195
579
  })));
@@ -1198,23 +582,22 @@ export const makeMessagesRecvSocket = (config) => {
1198
582
  else {
1199
583
  ev.emit('messages.update', ids.map(id => ({
1200
584
  key: { ...key, id },
1201
- update: { status, messageTimestamp: toNumber(+(attrs.t ?? 0)) }
585
+ update: { status }
1202
586
  })));
1203
587
  }
1204
588
  }
1205
589
  if (attrs.type === 'retry') {
1206
590
  // correctly set who is asking for the retry
1207
591
  key.participant = key.participant || attrs.from;
1208
- const retryNode = getBinaryNodeChild(node, 'retry');
1209
- if (ids[0] && key.participant && (await willSendMessageAgain(ids[0], key.participant))) {
592
+ const retryNode = (0, WABinary_1.getBinaryNodeChild)(node, 'retry');
593
+ if (willSendMessageAgain(ids[0], key.participant)) {
1210
594
  if (key.fromMe) {
1211
595
  try {
1212
- await updateSendMessageAgainCount(ids[0], key.participant);
1213
596
  logger.debug({ attrs, key }, 'recv retry request');
1214
- await sendMessagesAgain(key, ids, retryNode, node);
597
+ await sendMessagesAgain(key, ids, retryNode);
1215
598
  }
1216
599
  catch (error) {
1217
- logger.error({ key, ids, trace: error instanceof Error ? error.stack : 'Unknown error' }, 'error in sending message again');
600
+ logger.error({ key, ids, trace: error.stack }, 'error in sending message again');
1218
601
  }
1219
602
  }
1220
603
  else {
@@ -1229,267 +612,219 @@ export const makeMessagesRecvSocket = (config) => {
1229
612
  ]);
1230
613
  }
1231
614
  finally {
1232
- await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack receipt'));
615
+ await sendMessageAck(node);
1233
616
  }
1234
617
  };
1235
618
  const handleNotification = async (node) => {
1236
619
  const remoteJid = node.attrs.from;
620
+ if (shouldIgnoreJid(remoteJid) && remoteJid !== '@s.whatsapp.net') {
621
+ logger.debug({ remoteJid, id: node.attrs.id }, 'ignored notification');
622
+ await sendMessageAck(node);
623
+ return;
624
+ }
1237
625
  try {
1238
626
  await Promise.all([
1239
- notificationMutex.mutex(async () => {
627
+ processingMutex.mutex(async () => {
628
+ var _a;
1240
629
  const msg = await processNotification(node);
1241
630
  if (msg) {
1242
- const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me.id);
1243
- const { senderAlt: participantAlt, addressingMode } = extractAddressingContext(node);
631
+ const fromMe = (0, WABinary_1.areJidsSameUser)(node.attrs.participant || remoteJid, authState.creds.me.id);
1244
632
  msg.key = {
1245
633
  remoteJid,
1246
634
  fromMe,
1247
635
  participant: node.attrs.participant,
1248
- participantAlt,
1249
- participantUsername: node.attrs.participant_username,
1250
- addressingMode,
1251
636
  id: node.attrs.id,
1252
637
  ...(msg.key || {})
1253
638
  };
1254
- msg.participant ?? (msg.participant = node.attrs.participant);
639
+ (_a = msg.participant) !== null && _a !== void 0 ? _a : (msg.participant = node.attrs.participant);
1255
640
  msg.messageTimestamp = +node.attrs.t;
1256
- const fullMsg = proto.WebMessageInfo.fromObject(msg);
641
+ const fullMsg = WAProto_1.proto.WebMessageInfo.fromObject(msg);
1257
642
  await upsertMessage(fullMsg, 'append');
1258
643
  }
1259
644
  })
1260
645
  ]);
1261
646
  }
1262
647
  finally {
1263
- await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack notification'));
648
+ await sendMessageAck(node);
1264
649
  }
1265
650
  };
1266
651
  const handleMessage = async (node) => {
1267
- const encNode = getBinaryNodeChild(node, 'enc');
652
+ var _a, _b, _c;
653
+ if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== '@s.whatsapp.net') {
654
+ logger.debug({ key: node.attrs.key }, 'ignored message');
655
+ await sendMessageAck(node);
656
+ return;
657
+ }
658
+ const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
1268
659
  // TODO: temporary fix for crashes and issues resulting of failed msmsg decryption
1269
- if (encNode?.attrs.type === 'msmsg') {
660
+ if (encNode && encNode.attrs.type === 'msmsg') {
1270
661
  logger.debug({ key: node.attrs.key }, 'ignored msmsg');
1271
- await sendMessageAck(node, NACK_REASONS.MissingMessageSecret);
662
+ await sendMessageAck(node);
1272
663
  return;
1273
664
  }
1274
- let acked = false;
1275
- try {
1276
- const { fullMessage: msg, category, author, decrypt } = decryptMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
1277
- const alt = msg.key.participantAlt || msg.key.remoteJidAlt;
1278
- // store new mappings we didn't have before
1279
- if (!!alt) {
1280
- const altServer = jidDecode(alt)?.server;
1281
- const primaryJid = msg.key.participant || msg.key.remoteJid;
1282
- if (altServer === 'lid') {
1283
- if (!(await signalRepository.lidMapping.getPNForLID(alt))) {
1284
- await signalRepository.lidMapping.storeLIDPNMappings([{ lid: alt, pn: primaryJid }]);
1285
- await signalRepository.migrateSession(primaryJid, alt);
1286
- }
1287
- }
1288
- else {
1289
- await signalRepository.lidMapping.storeLIDPNMappings([{ lid: primaryJid, pn: alt }]);
1290
- await signalRepository.migrateSession(alt, primaryJid);
1291
- }
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;
1292
672
  }
1293
- await messageMutex.mutex(async () => {
1294
- await decrypt();
1295
- if (msg.key?.remoteJid && msg.key?.id && msg.message && messageRetryManager) {
1296
- messageRetryManager.addRecentMessage(msg.key.remoteJid, msg.key.id, msg.message);
1297
- }
1298
- // message failed to decrypt
1299
- if (msg.messageStubType === proto.WebMessageInfo.StubType.CIPHERTEXT && msg.category !== 'peer') {
1300
- if (msg?.messageStubParameters?.[0] === MISSING_KEYS_ERROR_TEXT) {
1301
- acked = true;
1302
- return sendMessageAck(node, NACK_REASONS.ParsingError);
1303
- }
1304
- if (msg.messageStubParameters?.[0] === NO_MESSAGE_FOUND_ERROR_TEXT) {
1305
- // Message arrived without encryption (e.g. CTWA ads messages).
1306
- // Check if this is eligible for placeholder resend (matching WA Web filters).
1307
- const unavailableNode = getBinaryNodeChild(node, 'unavailable');
1308
- const unavailableType = unavailableNode?.attrs?.type;
1309
- if (unavailableType === 'bot_unavailable_fanout' ||
1310
- unavailableType === 'hosted_unavailable_fanout' ||
1311
- unavailableType === 'view_once_unavailable_fanout') {
1312
- logger.debug({ msgId: msg.key.id, unavailableType }, 'skipping placeholder resend for excluded unavailable type');
1313
- acked = true;
1314
- return sendMessageAck(node);
1315
- }
1316
- const messageAge = unixTimestampSeconds() - toNumber(msg.messageTimestamp);
1317
- if (messageAge > PLACEHOLDER_MAX_AGE_SECONDS) {
1318
- logger.debug({ msgId: msg.key.id, messageAge }, 'skipping placeholder resend for old message');
1319
- acked = true;
1320
- return sendMessageAck(node);
1321
- }
1322
- // Request the real content from the phone via placeholder resend PDO.
1323
- // Upsert the CIPHERTEXT stub as a placeholder (like WA Web's processPlaceholderMsg),
1324
- // and store the requestId in stubParameters[1] so users can correlate
1325
- // with the incoming PDO response event.
1326
- const cleanKey = {
1327
- remoteJid: msg.key.remoteJid,
1328
- fromMe: msg.key.fromMe,
1329
- id: msg.key.id,
1330
- participant: msg.key.participant
1331
- };
1332
- // Cache the original message metadata so the PDO response handler
1333
- // can preserve key fields (LID details etc.) that the phone may omit
1334
- const msgData = {
1335
- key: msg.key,
1336
- messageTimestamp: msg.messageTimestamp,
1337
- pushName: msg.pushName,
1338
- participant: msg.participant,
1339
- verifiedBizName: msg.verifiedBizName
1340
- };
1341
- requestPlaceholderResend(cleanKey, msgData)
1342
- .then(requestId => {
1343
- if (requestId && requestId !== 'RESOLVED') {
1344
- logger.debug({ msgId: msg.key.id, requestId }, 'requested placeholder resend for unavailable message');
1345
- ev.emit('messages.update', [
1346
- {
1347
- key: msg.key,
1348
- update: { messageStubParameters: [NO_MESSAGE_FOUND_ERROR_TEXT, requestId] }
1349
- }
1350
- ]);
1351
- }
1352
- })
1353
- .catch(err => {
1354
- logger.warn({ err, msgId: msg.key.id }, 'failed to request placeholder resend for unavailable message');
1355
- });
1356
- acked = true;
1357
- await sendMessageAck(node);
1358
- // Don't return — fall through to upsertMessage so the stub is emitted
1359
- }
1360
- else {
1361
- // Skip retry for expired status messages (>24h old)
1362
- if (isJidStatusBroadcast(msg.key.remoteJid)) {
1363
- const messageAge = unixTimestampSeconds() - toNumber(msg.messageTimestamp);
1364
- if (messageAge > STATUS_EXPIRY_SECONDS) {
1365
- logger.debug({ msgId: msg.key.id, messageAge, remoteJid: msg.key.remoteJid }, 'skipping retry for expired status message');
1366
- acked = true;
1367
- return sendMessageAck(node);
1368
- }
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
+ }
687
+ 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);
1369
696
  }
1370
- logger.debug('[handleMessage] Attempting retry request for failed decryption');
1371
- // WAWeb only retry-receipts here; server emits PreKeyLow if prekeys run low.
1372
- await retryMutex.mutex(async () => {
1373
- try {
1374
- if (!ws.isOpen) {
1375
- logger.debug({ node }, 'Connection closed, skipping retry');
697
+ retryMutex.mutex(async () => {
698
+ if (ws.isOpen) {
699
+ if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable')) {
1376
700
  return;
1377
701
  }
1378
- const encNode = getBinaryNodeChild(node, 'enc');
702
+ const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
1379
703
  await sendRetryRequest(node, !encNode);
1380
704
  if (retryRequestDelayMs) {
1381
- await delay(retryRequestDelayMs);
705
+ await (0, Utils_1.delay)(retryRequestDelayMs);
1382
706
  }
1383
707
  }
1384
- catch (err) {
1385
- logger.error({ err }, 'Failed to send retry');
708
+ else {
709
+ logger.debug({ node }, 'connection closed, ignoring retry req');
1386
710
  }
1387
- acked = true;
1388
- await sendMessageAck(node, NACK_REASONS.UnhandledError);
1389
711
  });
1390
712
  }
1391
- }
1392
- else {
1393
- if (messageRetryManager && msg.key.id) {
1394
- messageRetryManager.cancelPendingPhoneRequest(msg.key.id);
1395
- }
1396
- const isNewsletter = isJidNewsletter(msg.key.remoteJid);
1397
- if (!isNewsletter) {
713
+ else {
1398
714
  // no type in the receipt => message delivered
1399
715
  let type = undefined;
1400
716
  let participant = msg.key.participant;
1401
- if (category === 'peer') {
1402
- // special peer message
717
+ if (category === 'peer') { // special peer message
1403
718
  type = 'peer_msg';
1404
719
  }
1405
- else if (msg.key.fromMe) {
1406
- // message was sent by us from a different device
720
+ else if (msg.key.fromMe) { // message was sent by us from a different device
1407
721
  type = 'sender';
1408
722
  // need to specially handle this case
1409
- if (isLidUser(msg.key.remoteJid) || isLidUser(msg.key.remoteJidAlt)) {
1410
- participant = author; // TODO: investigate sending receipts to LIDs and not PNs
723
+ if ((0, WABinary_1.isJidUser)(msg.key.remoteJid)) {
724
+ participant = author;
1411
725
  }
1412
726
  }
1413
727
  else if (!sendActiveReceipts) {
1414
728
  type = 'inactive';
1415
729
  }
1416
- acked = true;
1417
730
  await sendReceipt(msg.key.remoteJid, participant, [msg.key.id], type);
1418
731
  // send ack for history message
1419
- const isAnyHistoryMsg = getHistoryMsg(msg.message);
732
+ const isAnyHistoryMsg = (0, Utils_1.getHistoryMsg)(msg.message);
1420
733
  if (isAnyHistoryMsg) {
1421
- const jid = jidNormalizedUser(msg.key.remoteJid);
1422
- await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync'); // TODO: investigate
734
+ const jid = (0, WABinary_1.jidNormalizedUser)(msg.key.remoteJid);
735
+ await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync');
1423
736
  }
1424
737
  }
1425
- else {
1426
- acked = true;
1427
- await sendMessageAck(node);
1428
- logger.debug({ key: msg.key }, 'processed newsletter message without receipts');
1429
- }
1430
- }
1431
- cleanMessage(msg, authState.creds.me.id, authState.creds.me.lid);
1432
- await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify');
1433
- });
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
+ ]);
1434
743
  }
1435
744
  catch (error) {
1436
- logger.error({ error, node: binaryNodeToString(node) }, 'error in handling message');
1437
- if (!acked) {
1438
- await sendMessageAck(node, NACK_REASONS.UnhandledError).catch(ackErr => logger.error({ ackErr }, 'failed to ack message after error'));
1439
- }
745
+ logger.error({ error, node }, 'error in handling message');
1440
746
  }
1441
747
  };
1442
- const handleCall = async (node) => {
1443
- try {
1444
- const { attrs } = node;
1445
- const [infoChild] = getAllBinaryNodeChildren(node);
1446
- if (!infoChild) {
1447
- throw new Boom('Missing call info in call node');
1448
- }
1449
- const status = getCallStatusFromNode(infoChild);
1450
- const callId = infoChild.attrs['call-id'];
1451
- const from = infoChild.attrs.from || infoChild.attrs['call-creator'];
1452
- const call = {
1453
- chatId: attrs.from,
1454
- from,
1455
- callerPn: infoChild.attrs['caller_pn'],
1456
- id: callId,
1457
- date: new Date(+attrs.t * 1000),
1458
- offline: !!attrs.offline,
1459
- status
1460
- };
1461
- if (status === 'relaylatency') {
1462
- const latencyValue = infoChild.attrs.latency || infoChild.attrs['latency_ms'] || infoChild.attrs['latency-ms'];
1463
- const latencyMs = latencyValue ? Number(latencyValue) : undefined;
1464
- if (Number.isFinite(latencyMs)) {
1465
- call.latencyMs = latencyMs;
1466
- }
1467
- }
1468
- if (status === 'offer') {
1469
- call.isVideo = !!getBinaryNodeChild(infoChild, 'video');
1470
- call.isGroup = infoChild.attrs.type === 'group' || !!infoChild.attrs['group-jid'];
1471
- call.groupJid = infoChild.attrs['group-jid'];
1472
- await callOfferCache.set(call.id, call);
1473
- }
1474
- const existingCall = await callOfferCache.get(call.id);
1475
- // use existing call info to populate this event
1476
- if (existingCall) {
1477
- call.isVideo = existingCall.isVideo;
1478
- call.isGroup = existingCall.isGroup;
1479
- call.callerPn = call.callerPn || existingCall.callerPn;
1480
- }
1481
- // delete data once call has ended
1482
- if (status === 'reject' || status === 'accept' || status === 'timeout' || status === 'terminate') {
1483
- await callOfferCache.del(call.id);
1484
- }
1485
- ev.emit('call', [call]);
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');
1486
752
  }
1487
- catch (error) {
1488
- logger.error({ error, node: binaryNodeToString(node) }, 'error in handling call');
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
+ };
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');
1489
769
  }
1490
- finally {
1491
- await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack call'));
770
+ if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
771
+ logger.debug({ messageKey }, 'already requested resend');
772
+ return;
773
+ }
774
+ else {
775
+ placeholderResendCache.set(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id, true);
1492
776
  }
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';
781
+ }
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);
1493
828
  };
1494
829
  const handleBadAck = async ({ attrs }) => {
1495
830
  const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id };
@@ -1509,58 +844,15 @@ export const makeMessagesRecvSocket = (config) => {
1509
844
  // error in acknowledgement,
1510
845
  // device could not display the message
1511
846
  if (attrs.error) {
1512
- const isReachoutTimelocked = attrs.error === String(NACK_REASONS.SenderReachoutTimelocked);
1513
- if (attrs.error === SERVER_ERROR_CODES.MessageAccountRestriction) {
1514
- // 463 = 1:1 message missing privacy token (tctoken). Usually means the
1515
- // account is restricted: WhatsApp blocks starting new chats but preserves
1516
- // existing ones, since established chats already carry a tctoken.
1517
- // WA Web prevents this client-side (disables the compose bar).
1518
- // No retry — retrying counts as another "reach out" and worsens the restriction.
1519
- logger.warn({ msgId: attrs.id, from: attrs.from }, 'error 463: account restricted or missing tctoken for contact');
1520
- const ackFrom = attrs.from;
1521
- if (ackFrom && !inFlight463Recoveries.has(ackFrom)) {
1522
- inFlight463Recoveries.add(ackFrom);
1523
- void (async () => {
1524
- try {
1525
- const getPNForLID = signalRepository.lidMapping.getPNForLID.bind(signalRepository.lidMapping);
1526
- const tcStorageJid = await resolveTcTokenJid(ackFrom, getLIDForPN);
1527
- const issueJid = await resolveIssuanceJid(ackFrom, sock.serverProps.lidTrustedTokenIssueToLid, getLIDForPN, getPNForLID);
1528
- const result = await issuePrivacyTokens([issueJid], unixTimestampSeconds());
1529
- await storeTcTokensFromIqResult({
1530
- result,
1531
- fallbackJid: tcStorageJid,
1532
- keys: authState.keys,
1533
- getLIDForPN,
1534
- onNewJidStored: trackTcTokenJid
1535
- });
1536
- logger.debug({ from: ackFrom }, 'completed 463 token recovery issuance');
1537
- }
1538
- catch (err) {
1539
- logger.debug({ from: ackFrom, err: err?.message }, 'failed 463 token recovery issuance');
1540
- }
1541
- finally {
1542
- inFlight463Recoveries.delete(ackFrom);
1543
- }
1544
- })();
1545
- }
1546
- }
1547
- else if (attrs.error === SERVER_ERROR_CODES.SmaxInvalid) {
1548
- logger.warn({ msgId: attrs.id, from: attrs.from }, 'smax-invalid (479): stanza rejected by server — likely stale device session or malformed addressing');
1549
- }
1550
- else if (isReachoutTimelocked) {
1551
- // user is temporarily restricted, fetch current restriction details
1552
- await fetchAccountReachoutTimelock().catch(err => logger.warn({ err }, 'failed to fetch reachout timelock'));
1553
- logger.warn({ attrs }, 'received error in ack');
1554
- }
1555
- else {
1556
- logger.warn({ attrs }, 'received error in ack');
1557
- }
847
+ logger.warn({ attrs }, 'received error in ack');
1558
848
  ev.emit('messages.update', [
1559
849
  {
1560
850
  key,
1561
851
  update: {
1562
- status: WAMessageStatus.ERROR,
1563
- messageStubParameters: isReachoutTimelocked ? [attrs.error, ACCOUNT_RESTRICTED_TEXT] : [attrs.error]
852
+ status: Types_1.WAMessageStatus.ERROR,
853
+ messageStubParameters: [
854
+ attrs.error
855
+ ]
1564
856
  }
1565
857
  }
1566
858
  ]);
@@ -1573,61 +865,69 @@ export const makeMessagesRecvSocket = (config) => {
1573
865
  await execTask();
1574
866
  ev.flush();
1575
867
  function execTask() {
1576
- return exec(node, false).catch(err => onUnexpectedError(err, identifier));
868
+ return exec(node, false)
869
+ .catch(err => onUnexpectedError(err, identifier));
1577
870
  }
1578
871
  };
1579
- const offlineNodeProcessor = makeOfflineNodeProcessor(new Map([
1580
- ['message', handleMessage],
1581
- ['call', handleCall],
1582
- ['receipt', handleReceipt],
1583
- ['notification', handleNotification]
1584
- ]), {
1585
- isWsOpen: () => ws.isOpen,
1586
- onUnexpectedError,
1587
- yieldToEventLoop: () => new Promise(resolve => setImmediate(resolve))
1588
- });
1589
- const processNode = async (type, node, identifier, exec) => {
1590
- // Fast path: ack and drop ignored JIDs before entering the buffer/queue
1591
- const from = node.attrs.from;
1592
- let ignoreJid = from;
1593
- if (type === 'receipt' && from) {
1594
- const attrs = node.attrs;
1595
- const isLid = attrs.from.includes('lid');
1596
- const isNodeFromMe = areJidsSameUser(attrs.participant || attrs.from, isLid ? authState.creds.me?.lid : authState.creds.me?.id);
1597
- ignoreJid = !isNodeFromMe || isJidGroup(attrs.from) ? attrs.from : attrs.recipient;
1598
- }
1599
- if (ignoreJid && ignoreJid !== S_WHATSAPP_NET && shouldIgnoreJid(ignoreJid)) {
1600
- await sendMessageAck(node, type === 'message' ? NACK_REASONS.UnhandledError : undefined);
1601
- return;
1602
- }
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) => {
1603
905
  const isOffline = !!node.attrs.offline;
1604
906
  if (isOffline) {
1605
907
  offlineNodeProcessor.enqueue(type, node);
1606
908
  }
1607
909
  else {
1608
- await processNodeWithBuffer(node, identifier, exec);
910
+ processNodeWithBuffer(node, identifier, exec);
1609
911
  }
1610
912
  };
1611
913
  // recv a message
1612
- ws.on('CB:message', async (node) => {
1613
- await processNode('message', node, 'processing message', handleMessage);
914
+ ws.on('CB:message', (node) => {
915
+ processNode('message', node, 'processing message', handleMessage);
1614
916
  });
1615
917
  ws.on('CB:call', async (node) => {
1616
- await processNode('call', node, 'handling call', handleCall);
918
+ processNode('call', node, 'handling call', handleCall);
1617
919
  });
1618
- ws.on('CB:receipt', async (node) => {
1619
- await processNode('receipt', node, 'handling receipt', handleReceipt);
920
+ ws.on('CB:receipt', node => {
921
+ processNode('receipt', node, 'handling receipt', handleReceipt);
1620
922
  });
1621
923
  ws.on('CB:notification', async (node) => {
1622
- await processNode('notification', node, 'handling notification', handleNotification);
924
+ processNode('notification', node, 'handling notification', handleNotification);
1623
925
  });
1624
926
  ws.on('CB:ack,class:message', (node) => {
1625
- handleBadAck(node).catch(error => onUnexpectedError(error, 'handling bad ack'));
927
+ handleBadAck(node)
928
+ .catch(error => onUnexpectedError(error, 'handling bad ack'));
1626
929
  });
1627
- ev.on('call', async ([call]) => {
1628
- if (!call) {
1629
- return;
1630
- }
930
+ ev.on('call', ([call]) => {
1631
931
  // missed call + group call notification message generation
1632
932
  if (call.status === 'timeout' || (call.status === 'offer' && call.isGroup)) {
1633
933
  const msg = {
@@ -1636,137 +936,37 @@ export const makeMessagesRecvSocket = (config) => {
1636
936
  id: call.id,
1637
937
  fromMe: false
1638
938
  },
1639
- messageTimestamp: unixTimestampSeconds(call.date)
939
+ messageTimestamp: (0, Utils_1.unixTimestampSeconds)(call.date),
1640
940
  };
1641
941
  if (call.status === 'timeout') {
1642
942
  if (call.isGroup) {
1643
- msg.messageStubType = call.isVideo
1644
- ? WAMessageStubType.CALL_MISSED_GROUP_VIDEO
1645
- : WAMessageStubType.CALL_MISSED_GROUP_VOICE;
943
+ msg.messageStubType = call.isVideo ? Types_1.WAMessageStubType.CALL_MISSED_GROUP_VIDEO : Types_1.WAMessageStubType.CALL_MISSED_GROUP_VOICE;
1646
944
  }
1647
945
  else {
1648
- msg.messageStubType = call.isVideo ? WAMessageStubType.CALL_MISSED_VIDEO : WAMessageStubType.CALL_MISSED_VOICE;
946
+ msg.messageStubType = call.isVideo ? Types_1.WAMessageStubType.CALL_MISSED_VIDEO : Types_1.WAMessageStubType.CALL_MISSED_VOICE;
1649
947
  }
1650
948
  }
1651
949
  else {
1652
950
  msg.message = { call: { callKey: Buffer.from(call.id) } };
1653
951
  }
1654
- const protoMsg = proto.WebMessageInfo.fromObject(msg);
1655
- await upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
952
+ const protoMsg = WAProto_1.proto.WebMessageInfo.fromObject(msg);
953
+ upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
1656
954
  }
1657
955
  });
1658
- /** timestamp of last tctoken prune run — throttles to once per 24h */
1659
- let lastTcTokenPruneTs = 0;
1660
- /** dedupe in-flight 463 recovery token issuance by target JID */
1661
- const inFlight463Recoveries = new Set();
1662
- ev.on('connection.update', ({ isOnline, connection }) => {
956
+ ev.on('connection.update', ({ isOnline }) => {
1663
957
  if (typeof isOnline !== 'undefined') {
1664
958
  sendActiveReceipts = isOnline;
1665
959
  logger.trace(`sendActiveReceipts set to "${sendActiveReceipts}"`);
1666
960
  }
1667
- // Flush pending tctoken index save on disconnect to avoid writing after close
1668
- if (connection === 'close' && tcTokenIndexTimer) {
1669
- clearTimeout(tcTokenIndexTimer);
1670
- tcTokenIndexTimer = undefined;
1671
- // Best-effort flush — may fail if store is already closed
1672
- try {
1673
- void Promise.resolve(flushTcTokenIndex()).catch(() => { });
1674
- }
1675
- catch {
1676
- /* ignore sync errors */
1677
- }
1678
- }
1679
- // Prune expired tctokens when coming online, at most once per 24 hours
1680
- // Matches WA Web's CLEAN_TC_TOKENS task
1681
- // Note: don't gate on tcTokenKnownJids.size — the index may still be loading
1682
- if (isOnline) {
1683
- const now = Date.now();
1684
- const DAY_MS = 24 * 60 * 60 * 1000;
1685
- if (now - lastTcTokenPruneTs >= DAY_MS) {
1686
- lastTcTokenPruneTs = now;
1687
- void pruneExpiredTcTokens();
1688
- }
1689
- }
1690
- });
1691
- registerSocketEndHandler(() => {
1692
- if (!config.msgRetryCounterCache && msgRetryCache.close) {
1693
- msgRetryCache.close();
1694
- }
1695
- if (!config.callOfferCache && callOfferCache.close) {
1696
- callOfferCache.close();
1697
- }
1698
- identityAssertDebounce.close();
1699
- sendActiveReceipts = false;
1700
961
  });
1701
- async function pruneExpiredTcTokens() {
1702
- try {
1703
- await tcTokenIndexLoaded;
1704
- // Union with the persisted index picks up JIDs added by other layers
1705
- // (history sync) without needing inter-module wiring.
1706
- const persisted = await readTcTokenIndex(authState.keys);
1707
- const allJids = new Set(tcTokenKnownJids);
1708
- for (const jid of persisted)
1709
- allJids.add(jid);
1710
- if (!allJids.size)
1711
- return;
1712
- const jids = [...allJids];
1713
- const allTokens = await authState.keys.get('tctoken', jids);
1714
- const writes = {};
1715
- const survivors = new Set();
1716
- let mutated = 0;
1717
- for (const jid of jids) {
1718
- const entry = allTokens[jid];
1719
- if (!entry) {
1720
- // Tracked but nothing in store — drop from index.
1721
- mutated++;
1722
- continue;
1723
- }
1724
- const hasPeerToken = !!entry.token?.length;
1725
- const peerTokenExpired = hasPeerToken && isTcTokenExpired(entry.timestamp);
1726
- const hasSenderTs = entry.senderTimestamp !== undefined;
1727
- const senderTsExpired = hasSenderTs && isTcTokenExpired(entry.senderTimestamp);
1728
- const keepPeerToken = hasPeerToken && !peerTokenExpired;
1729
- const keepSenderTs = hasSenderTs && !senderTsExpired;
1730
- if (!keepPeerToken && !keepSenderTs) {
1731
- writes[jid] = null;
1732
- mutated++;
1733
- }
1734
- else if (peerTokenExpired && keepSenderTs) {
1735
- writes[jid] = { token: Buffer.alloc(0), senderTimestamp: entry.senderTimestamp };
1736
- survivors.add(jid);
1737
- mutated++;
1738
- }
1739
- else {
1740
- survivors.add(jid);
1741
- }
1742
- }
1743
- if (mutated === 0)
1744
- return;
1745
- await authState.keys.set({
1746
- tctoken: {
1747
- ...writes,
1748
- [TC_TOKEN_INDEX_KEY]: {
1749
- token: Buffer.from(JSON.stringify([...survivors]))
1750
- }
1751
- }
1752
- });
1753
- tcTokenKnownJids.clear();
1754
- for (const jid of survivors)
1755
- tcTokenKnownJids.add(jid);
1756
- logger.debug({ mutated, remaining: survivors.size }, 'pruned expired tctokens');
1757
- }
1758
- catch (err) {
1759
- logger.warn({ err: err?.message }, 'failed to prune expired tctokens');
1760
- }
1761
- }
1762
962
  return {
1763
963
  ...sock,
1764
964
  sendMessageAck,
1765
965
  sendRetryRequest,
966
+ offerCall,
1766
967
  rejectCall,
1767
968
  fetchMessageHistory,
1768
969
  requestPlaceholderResend,
1769
- messageRetryManager
1770
970
  };
1771
971
  };
1772
- //# sourceMappingURL=messages-recv.js.map
972
+ exports.makeMessagesRecvSocket = makeMessagesRecvSocket;