@queenanya/baileys 9.2.1 → 9.4.1

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 (327) hide show
  1. package/README.md +349 -1171
  2. package/WAProto/fix-imports.js +74 -18
  3. package/WAProto/index.js +201 -160
  4. package/engine-requirements.js +7 -7
  5. package/lib/Defaults/index.d.ts +19 -0
  6. package/lib/Defaults/index.d.ts.map +1 -1
  7. package/lib/Defaults/index.js +32 -6
  8. package/lib/Defaults/index.js.map +1 -1
  9. package/lib/Signal/libsignal.d.ts.map +1 -1
  10. package/lib/Signal/libsignal.js +61 -2
  11. package/lib/Signal/libsignal.js.map +1 -1
  12. package/lib/Signal/lid-mapping.d.ts +5 -9
  13. package/lib/Signal/lid-mapping.d.ts.map +1 -1
  14. package/lib/Signal/lid-mapping.js +170 -70
  15. package/lib/Signal/lid-mapping.js.map +1 -1
  16. package/lib/Socket/Client/websocket.d.ts +1 -1
  17. package/lib/Socket/Client/websocket.d.ts.map +1 -1
  18. package/lib/Socket/Client/websocket.js +5 -1
  19. package/lib/Socket/Client/websocket.js.map +1 -1
  20. package/lib/Socket/business.d.ts +125 -5
  21. package/lib/Socket/business.d.ts.map +1 -1
  22. package/lib/Socket/business.js +11 -8
  23. package/lib/Socket/business.js.map +1 -1
  24. package/lib/Socket/chats.d.ts +22 -3
  25. package/lib/Socket/chats.d.ts.map +1 -1
  26. package/lib/Socket/chats.js +277 -58
  27. package/lib/Socket/chats.js.map +1 -1
  28. package/lib/Socket/communities.d.ts +125 -5
  29. package/lib/Socket/communities.d.ts.map +1 -1
  30. package/lib/Socket/groups.d.ts +19 -3
  31. package/lib/Socket/groups.d.ts.map +1 -1
  32. package/lib/Socket/groups.js +7 -1
  33. package/lib/Socket/groups.js.map +1 -1
  34. package/lib/Socket/index.d.ts +125 -5
  35. package/lib/Socket/index.d.ts.map +1 -1
  36. package/lib/Socket/index.js +0 -6
  37. package/lib/Socket/index.js.map +1 -1
  38. package/lib/Socket/messages-recv.d.ts +126 -6
  39. package/lib/Socket/messages-recv.d.ts.map +1 -1
  40. package/lib/Socket/messages-recv.js +771 -177
  41. package/lib/Socket/messages-recv.js.map +1 -1
  42. package/lib/Socket/messages-send.d.ts +129 -7
  43. package/lib/Socket/messages-send.d.ts.map +1 -1
  44. package/lib/Socket/messages-send.js +430 -119
  45. package/lib/Socket/messages-send.js.map +1 -1
  46. package/lib/Socket/newsletter.d.ts +20 -5
  47. package/lib/Socket/newsletter.d.ts.map +1 -1
  48. package/lib/Socket/newsletter.js +2 -47
  49. package/lib/Socket/newsletter.js.map +1 -1
  50. package/lib/Socket/socket.d.ts +3 -1
  51. package/lib/Socket/socket.d.ts.map +1 -1
  52. package/lib/Socket/socket.js +151 -29
  53. package/lib/Socket/socket.js.map +1 -1
  54. package/lib/Types/Auth.d.ts +2 -0
  55. package/lib/Types/Auth.d.ts.map +1 -1
  56. package/lib/Types/Call.d.ts +10 -1
  57. package/lib/Types/Call.d.ts.map +1 -1
  58. package/lib/Types/Contact.d.ts +2 -0
  59. package/lib/Types/Contact.d.ts.map +1 -1
  60. package/lib/Types/Events.d.ts +60 -6
  61. package/lib/Types/Events.d.ts.map +1 -1
  62. package/lib/Types/GroupMetadata.d.ts +4 -0
  63. package/lib/Types/GroupMetadata.d.ts.map +1 -1
  64. package/lib/Types/Message.d.ts +530 -16
  65. package/lib/Types/Message.d.ts.map +1 -1
  66. package/lib/Types/Message.js.map +1 -1
  67. package/lib/Types/Newsletter.d.ts +32 -45
  68. package/lib/Types/Newsletter.d.ts.map +1 -1
  69. package/lib/Types/Newsletter.js +25 -23
  70. package/lib/Types/Newsletter.js.map +1 -1
  71. package/lib/Types/State.d.ts +54 -0
  72. package/lib/Types/State.d.ts.map +1 -1
  73. package/lib/Types/State.js +42 -0
  74. package/lib/Types/State.js.map +1 -1
  75. package/lib/Types/index.d.ts +9 -0
  76. package/lib/Types/index.d.ts.map +1 -1
  77. package/lib/Types/index.js.map +1 -1
  78. package/lib/Utils/auth-utils.d.ts.map +1 -1
  79. package/lib/Utils/auth-utils.js +53 -20
  80. package/lib/Utils/auth-utils.js.map +1 -1
  81. package/lib/Utils/browser-utils.d.ts +13 -0
  82. package/lib/Utils/browser-utils.d.ts.map +1 -1
  83. package/lib/Utils/browser-utils.js +90 -10
  84. package/lib/Utils/browser-utils.js.map +1 -1
  85. package/lib/Utils/chat-utils.d.ts +30 -0
  86. package/lib/Utils/chat-utils.d.ts.map +1 -1
  87. package/lib/Utils/chat-utils.js +134 -59
  88. package/lib/Utils/chat-utils.js.map +1 -1
  89. package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
  90. package/lib/Utils/companion-reg-client-utils.d.ts.map +1 -0
  91. package/lib/Utils/companion-reg-client-utils.js +34 -0
  92. package/lib/Utils/companion-reg-client-utils.js.map +1 -0
  93. package/lib/Utils/crypto.d.ts +4 -8
  94. package/lib/Utils/crypto.d.ts.map +1 -1
  95. package/lib/Utils/crypto.js +2 -26
  96. package/lib/Utils/crypto.js.map +1 -1
  97. package/lib/Utils/decode-wa-message.d.ts +12 -0
  98. package/lib/Utils/decode-wa-message.d.ts.map +1 -1
  99. package/lib/Utils/decode-wa-message.js +16 -0
  100. package/lib/Utils/decode-wa-message.js.map +1 -1
  101. package/lib/Utils/event-buffer.d.ts.map +1 -1
  102. package/lib/Utils/event-buffer.js +43 -8
  103. package/lib/Utils/event-buffer.js.map +1 -1
  104. package/lib/Utils/generics.d.ts +3 -1
  105. package/lib/Utils/generics.d.ts.map +1 -1
  106. package/lib/Utils/generics.js +17 -4
  107. package/lib/Utils/generics.js.map +1 -1
  108. package/lib/Utils/history.d.ts +8 -3
  109. package/lib/Utils/history.d.ts.map +1 -1
  110. package/lib/Utils/history.js +60 -16
  111. package/lib/Utils/history.js.map +1 -1
  112. package/lib/Utils/identity-change-handler.d.ts +44 -0
  113. package/lib/Utils/identity-change-handler.d.ts.map +1 -0
  114. package/lib/Utils/identity-change-handler.js +50 -0
  115. package/lib/Utils/identity-change-handler.js.map +1 -0
  116. package/lib/Utils/index.d.ts +6 -0
  117. package/lib/Utils/index.d.ts.map +1 -1
  118. package/lib/Utils/index.js +6 -0
  119. package/lib/Utils/index.js.map +1 -1
  120. package/lib/Utils/interactive-message.d.ts +201 -0
  121. package/lib/Utils/interactive-message.d.ts.map +1 -0
  122. package/lib/Utils/interactive-message.js +256 -0
  123. package/lib/Utils/interactive-message.js.map +1 -0
  124. package/lib/Utils/lt-hash.d.ts +7 -12
  125. package/lib/Utils/lt-hash.d.ts.map +1 -1
  126. package/lib/Utils/lt-hash.js +2 -42
  127. package/lib/Utils/lt-hash.js.map +1 -1
  128. package/lib/Utils/make-mutex.d.ts +1 -0
  129. package/lib/Utils/make-mutex.d.ts.map +1 -1
  130. package/lib/Utils/make-mutex.js +20 -27
  131. package/lib/Utils/make-mutex.js.map +1 -1
  132. package/lib/Utils/message-composer.d.ts +5 -0
  133. package/lib/Utils/message-composer.d.ts.map +1 -0
  134. package/lib/Utils/message-composer.js +5 -0
  135. package/lib/Utils/message-composer.js.map +1 -0
  136. package/lib/Utils/message-retry-manager.d.ts +30 -2
  137. package/lib/Utils/message-retry-manager.d.ts.map +1 -1
  138. package/lib/Utils/message-retry-manager.js +58 -5
  139. package/lib/Utils/message-retry-manager.js.map +1 -1
  140. package/lib/Utils/messages-media.d.ts +35 -5
  141. package/lib/Utils/messages-media.d.ts.map +1 -1
  142. package/lib/Utils/messages-media.js +171 -51
  143. package/lib/Utils/messages-media.js.map +1 -1
  144. package/lib/Utils/messages.d.ts +2 -0
  145. package/lib/Utils/messages.d.ts.map +1 -1
  146. package/lib/Utils/messages.js +475 -35
  147. package/lib/Utils/messages.js.map +1 -1
  148. package/lib/Utils/noise-handler.d.ts +4 -4
  149. package/lib/Utils/noise-handler.d.ts.map +1 -1
  150. package/lib/Utils/noise-handler.js +139 -85
  151. package/lib/Utils/noise-handler.js.map +1 -1
  152. package/lib/Utils/offline-node-processor.d.ts +17 -0
  153. package/lib/Utils/offline-node-processor.d.ts.map +1 -0
  154. package/lib/Utils/offline-node-processor.js +40 -0
  155. package/lib/Utils/offline-node-processor.js.map +1 -0
  156. package/lib/Utils/process-message.d.ts.map +1 -1
  157. package/lib/Utils/process-message.js +115 -16
  158. package/lib/Utils/process-message.js.map +1 -1
  159. package/lib/Utils/reporting-utils.d.ts +11 -0
  160. package/lib/Utils/reporting-utils.d.ts.map +1 -0
  161. package/lib/Utils/reporting-utils.js +258 -0
  162. package/lib/Utils/reporting-utils.js.map +1 -0
  163. package/lib/Utils/stanza-ack.d.ts +11 -0
  164. package/lib/Utils/stanza-ack.d.ts.map +1 -0
  165. package/lib/Utils/stanza-ack.js +38 -0
  166. package/lib/Utils/stanza-ack.js.map +1 -0
  167. package/lib/Utils/sync-action-utils.d.ts +19 -0
  168. package/lib/Utils/sync-action-utils.d.ts.map +1 -0
  169. package/lib/Utils/sync-action-utils.js +49 -0
  170. package/lib/Utils/sync-action-utils.js.map +1 -0
  171. package/lib/Utils/tc-token-utils.d.ts +37 -0
  172. package/lib/Utils/tc-token-utils.d.ts.map +1 -0
  173. package/lib/Utils/tc-token-utils.js +163 -0
  174. package/lib/Utils/tc-token-utils.js.map +1 -0
  175. package/lib/Utils/use-mongo-file-auth-state.d.ts +16 -0
  176. package/lib/Utils/use-mongo-file-auth-state.d.ts.map +1 -0
  177. package/lib/Utils/use-mongo-file-auth-state.js +60 -0
  178. package/lib/Utils/use-mongo-file-auth-state.js.map +1 -0
  179. package/lib/Utils/use-multi-file-auth-state.js +1 -1
  180. package/lib/Utils/use-multi-file-auth-state.js.map +1 -1
  181. package/lib/Utils/use-single-file-auth-state.d.ts.map +1 -1
  182. package/lib/Utils/use-single-file-auth-state.js.map +1 -1
  183. package/lib/Utils/validate-connection.d.ts.map +1 -1
  184. package/lib/Utils/validate-connection.js +11 -1
  185. package/lib/Utils/validate-connection.js.map +1 -1
  186. package/lib/WABinary/decode.d.ts.map +1 -1
  187. package/lib/WABinary/decode.js +24 -0
  188. package/lib/WABinary/decode.js.map +1 -1
  189. package/lib/WABinary/encode.js +5 -1
  190. package/lib/WABinary/encode.js.map +1 -1
  191. package/lib/WABinary/generic-utils.d.ts +10 -1
  192. package/lib/WABinary/generic-utils.d.ts.map +1 -1
  193. package/lib/WABinary/generic-utils.js +42 -8
  194. package/lib/WABinary/generic-utils.js.map +1 -1
  195. package/lib/WABinary/jid-utils.js.map +1 -1
  196. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -1
  197. package/lib/WAUSync/Protocols/USyncContactProtocol.js +26 -3
  198. package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -1
  199. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
  200. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
  201. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
  202. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
  203. package/lib/WAUSync/Protocols/index.d.ts +1 -0
  204. package/lib/WAUSync/Protocols/index.d.ts.map +1 -1
  205. package/lib/WAUSync/Protocols/index.js +1 -0
  206. package/lib/WAUSync/Protocols/index.js.map +1 -1
  207. package/lib/WAUSync/USyncQuery.d.ts +1 -0
  208. package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
  209. package/lib/WAUSync/USyncQuery.js +6 -2
  210. package/lib/WAUSync/USyncQuery.js.map +1 -1
  211. package/lib/WAUSync/USyncUser.d.ts +4 -0
  212. package/lib/WAUSync/USyncUser.d.ts.map +1 -1
  213. package/lib/WAUSync/USyncUser.js +8 -0
  214. package/lib/WAUSync/USyncUser.js.map +1 -1
  215. package/lib/addons/anti-delete.d.ts +72 -0
  216. package/lib/addons/anti-delete.d.ts.map +1 -0
  217. package/lib/addons/anti-delete.js +165 -0
  218. package/lib/addons/anti-delete.js.map +1 -0
  219. package/lib/addons/auto-reply.d.ts +67 -0
  220. package/lib/addons/auto-reply.d.ts.map +1 -0
  221. package/lib/addons/auto-reply.js +145 -0
  222. package/lib/addons/auto-reply.js.map +1 -0
  223. package/lib/addons/browser-presets.d.ts +16 -0
  224. package/lib/addons/browser-presets.d.ts.map +1 -0
  225. package/lib/addons/browser-presets.js +24 -0
  226. package/lib/addons/browser-presets.js.map +1 -0
  227. package/lib/addons/button-sender.d.ts +260 -0
  228. package/lib/addons/button-sender.d.ts.map +1 -0
  229. package/lib/addons/button-sender.js +771 -0
  230. package/lib/addons/button-sender.js.map +1 -0
  231. package/lib/addons/call-handler.d.ts +79 -0
  232. package/lib/addons/call-handler.d.ts.map +1 -0
  233. package/lib/addons/call-handler.js +342 -0
  234. package/lib/addons/call-handler.js.map +1 -0
  235. package/lib/addons/from-chats.d.ts +30 -0
  236. package/lib/addons/from-chats.d.ts.map +1 -0
  237. package/lib/addons/from-chats.js +38 -0
  238. package/lib/addons/from-chats.js.map +1 -0
  239. package/lib/addons/from-messages-recv.d.ts +59 -0
  240. package/lib/addons/from-messages-recv.d.ts.map +1 -0
  241. package/lib/addons/from-messages-recv.js +326 -0
  242. package/lib/addons/from-messages-recv.js.map +1 -0
  243. package/lib/addons/from-messages-send.d.ts +50 -0
  244. package/lib/addons/from-messages-send.d.ts.map +1 -0
  245. package/lib/addons/from-messages-send.js +148 -0
  246. package/lib/addons/from-messages-send.js.map +1 -0
  247. package/lib/addons/from-messages.d.ts +52 -0
  248. package/lib/addons/from-messages.d.ts.map +1 -0
  249. package/lib/addons/from-messages.js +304 -0
  250. package/lib/addons/from-messages.js.map +1 -0
  251. package/lib/addons/index.d.ts +67 -0
  252. package/lib/addons/index.d.ts.map +1 -0
  253. package/lib/addons/index.js +86 -0
  254. package/lib/addons/index.js.map +1 -0
  255. package/lib/addons/interactive-message.d.ts +201 -0
  256. package/lib/addons/interactive-message.d.ts.map +1 -0
  257. package/lib/addons/interactive-message.js +256 -0
  258. package/lib/addons/interactive-message.js.map +1 -0
  259. package/lib/addons/jid-plot.d.ts +49 -0
  260. package/lib/addons/jid-plot.d.ts.map +1 -0
  261. package/lib/addons/jid-plot.js +84 -0
  262. package/lib/addons/jid-plot.js.map +1 -0
  263. package/lib/addons/jid-plotting.d.ts +54 -0
  264. package/lib/addons/jid-plotting.d.ts.map +1 -0
  265. package/lib/addons/jid-plotting.js +150 -0
  266. package/lib/addons/jid-plotting.js.map +1 -0
  267. package/lib/addons/lid-support.d.ts +41 -0
  268. package/lib/addons/lid-support.d.ts.map +1 -0
  269. package/lib/addons/lid-support.js +42 -0
  270. package/lib/addons/lid-support.js.map +1 -0
  271. package/lib/addons/message-composer.d.ts +142 -0
  272. package/lib/addons/message-composer.d.ts.map +1 -0
  273. package/lib/addons/message-composer.js +377 -0
  274. package/lib/addons/message-composer.js.map +1 -0
  275. package/lib/addons/message-scheduler.d.ts +77 -0
  276. package/lib/addons/message-scheduler.d.ts.map +1 -0
  277. package/lib/addons/message-scheduler.js +108 -0
  278. package/lib/addons/message-scheduler.js.map +1 -0
  279. package/lib/addons/message-search.d.ts +51 -0
  280. package/lib/addons/message-search.d.ts.map +1 -0
  281. package/lib/addons/message-search.js +171 -0
  282. package/lib/addons/message-search.js.map +1 -0
  283. package/lib/addons/message-utils.d.ts +88 -0
  284. package/lib/addons/message-utils.d.ts.map +1 -0
  285. package/lib/addons/message-utils.js +292 -0
  286. package/lib/addons/message-utils.js.map +1 -0
  287. package/lib/addons/outgoing-calls.d.ts +64 -0
  288. package/lib/addons/outgoing-calls.d.ts.map +1 -0
  289. package/lib/addons/outgoing-calls.js +139 -0
  290. package/lib/addons/outgoing-calls.js.map +1 -0
  291. package/lib/addons/pairing-fix.d.ts +31 -0
  292. package/lib/addons/pairing-fix.d.ts.map +1 -0
  293. package/lib/addons/pairing-fix.js +74 -0
  294. package/lib/addons/pairing-fix.js.map +1 -0
  295. package/lib/addons/past-participants.d.ts +42 -0
  296. package/lib/addons/past-participants.d.ts.map +1 -0
  297. package/lib/addons/past-participants.js +41 -0
  298. package/lib/addons/past-participants.js.map +1 -0
  299. package/lib/addons/rich-response.d.ts +111 -0
  300. package/lib/addons/rich-response.d.ts.map +1 -0
  301. package/lib/addons/rich-response.js +152 -0
  302. package/lib/addons/rich-response.js.map +1 -0
  303. package/lib/addons/scheduling.d.ts +41 -0
  304. package/lib/addons/scheduling.d.ts.map +1 -0
  305. package/lib/addons/scheduling.js +110 -0
  306. package/lib/addons/scheduling.js.map +1 -0
  307. package/lib/addons/status-posting.d.ts +177 -0
  308. package/lib/addons/status-posting.d.ts.map +1 -0
  309. package/lib/addons/status-posting.js +240 -0
  310. package/lib/addons/status-posting.js.map +1 -0
  311. package/lib/addons/stickerpack.d.ts +37 -0
  312. package/lib/addons/stickerpack.d.ts.map +1 -0
  313. package/lib/addons/stickerpack.js +39 -0
  314. package/lib/addons/stickerpack.js.map +1 -0
  315. package/lib/addons/templates.d.ts +72 -0
  316. package/lib/addons/templates.d.ts.map +1 -0
  317. package/lib/addons/templates.js +145 -0
  318. package/lib/addons/templates.js.map +1 -0
  319. package/lib/addons/vcard.d.ts +59 -0
  320. package/lib/addons/vcard.d.ts.map +1 -0
  321. package/lib/addons/vcard.js +88 -0
  322. package/lib/addons/vcard.js.map +1 -0
  323. package/lib/index.d.ts +1 -0
  324. package/lib/index.d.ts.map +1 -1
  325. package/lib/index.js +1 -0
  326. package/lib/index.js.map +1 -1
  327. package/package.json +6 -3
@@ -1,17 +1,29 @@
1
1
  import NodeCache from '@cacheable/node-cache';
2
2
  import { Boom } from '@hapi/boom';
3
+ import { randomBytes } from 'crypto';
3
4
  import { proto } from '../../WAProto/index.js';
5
+ import { execSendStatusMentions } from '../addons/from-messages-send.js';
6
+ import { extractUnifiedResponse, generateCodeBlockContent, generateLatexContent, generateLatexImageContent, generateLatexInlineImageContent, generateListContent, generateRichMessageContent, generateTableContent, generateUnifiedResponseContent } from '../addons/message-composer.js';
7
+ import { getButtonArgs, getButtonType, getMediaType, getMessageType } from '../addons/message-utils.js';
4
8
  import { DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
5
- import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
9
+ import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, delay, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, generateWAMessageFromContent, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
6
10
  import { getUrlInfo } from '../Utils/link-preview.js';
7
11
  import { makeKeyedMutex } from '../Utils/make-mutex.js';
8
- import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidGroup, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
12
+ import { getMessageReportingToken, shouldIncludeReportingToken } from '../Utils/reporting-utils.js';
13
+ import { buildMergedTcTokenIndexWrite, isTcTokenExpired, resolveIssuanceJid, resolveTcTokenJid, shouldSendNewTcToken, storeTcTokensFromIqResult } from '../Utils/tc-token-utils.js';
14
+ import { areJidsSameUser, getBinaryFilteredBizBot, getBinaryFilteredButtons, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidBot, isJidGroup, isJidMetaAI, isJidNewsletter, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, PSA_WID, S_WHATSAPP_NET } from '../WABinary/index.js';
9
15
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
10
16
  import { makeNewsletterSocket } from './newsletter.js';
11
17
  export const makeMessagesSocket = (config) => {
12
18
  const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
13
19
  const sock = makeNewsletterSocket(config);
14
- const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral } = sock;
20
+ const { ev, authState, messageMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral } = sock;
21
+ const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
22
+ /**
23
+ * Set of tctoken storage JIDs with a fire-and-forget `issuePrivacyTokens` IQ in flight.
24
+ * Prevents duplicate IQs from rapid back-to-back sends before `senderTimestamp` persists.
25
+ */
26
+ const inFlightTcTokenIssuance = new Set();
15
27
  const userDevicesCache = config.userDevicesCache ||
16
28
  new NodeCache({
17
29
  stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
@@ -254,6 +266,34 @@ export const makeMessagesSocket = (config) => {
254
266
  }
255
267
  return deviceResults;
256
268
  };
269
+ /**
270
+ * Update Member Label
271
+ */
272
+ const updateMemberLabel = (jid, memberLabel) => {
273
+ if (!isJidGroup(jid)) {
274
+ throw new Error('Jid must a group jid!');
275
+ }
276
+ return relayMessage(jid, {
277
+ protocolMessage: {
278
+ type: proto.Message.ProtocolMessage.Type.GROUP_MEMBER_LABEL_CHANGE,
279
+ memberLabel: {
280
+ label: memberLabel?.slice(0, 30),
281
+ labelTimestamp: unixTimestampSeconds()
282
+ }
283
+ }
284
+ }, {
285
+ additionalNodes: [
286
+ {
287
+ tag: 'meta',
288
+ attrs: {
289
+ tag_reason: 'user_update',
290
+ appdata: 'member_tag'
291
+ },
292
+ content: undefined
293
+ }
294
+ ]
295
+ });
296
+ };
257
297
  const assertSessions = async (jids, force) => {
258
298
  let didFetchNewSession = false;
259
299
  const uniqueJids = [...new Set(jids)]; // Deduplicate JIDs
@@ -354,59 +394,63 @@ export const makeMessagesSocket = (config) => {
354
394
  const meLid = authState.creds.me?.lid;
355
395
  const meLidUser = meLid ? jidDecode(meLid)?.user : null;
356
396
  const encryptionPromises = patchedMessages.map(async ({ recipientJid: jid, message: patchedMessage }) => {
357
- if (!jid)
358
- return null;
359
- let msgToEncrypt = patchedMessage;
360
- if (dsmMessage) {
361
- const { user: targetUser } = jidDecode(jid);
362
- const { user: ownPnUser } = jidDecode(meId);
363
- const ownLidUser = meLidUser;
364
- const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
365
- const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
366
- if (isOwnUser && !isExactSenderDevice) {
367
- msgToEncrypt = dsmMessage;
368
- logger.debug({ jid, targetUser }, 'Using DSM for own device');
369
- }
370
- }
371
- const bytes = encodeWAMessage(msgToEncrypt);
372
- const mutexKey = jid;
373
- const node = await encryptionMutex.mutex(mutexKey, async () => {
374
- const { type, ciphertext } = await signalRepository.encryptMessage({
375
- jid,
376
- data: bytes
397
+ try {
398
+ if (!jid)
399
+ return null;
400
+ let msgToEncrypt = patchedMessage;
401
+ if (dsmMessage) {
402
+ const { user: targetUser } = jidDecode(jid);
403
+ const { user: ownPnUser } = jidDecode(meId);
404
+ const ownLidUser = meLidUser;
405
+ const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
406
+ const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
407
+ if (isOwnUser && !isExactSenderDevice) {
408
+ msgToEncrypt = dsmMessage;
409
+ logger.debug({ jid, targetUser }, 'Using DSM for own device');
410
+ }
411
+ }
412
+ const bytes = encodeWAMessage(msgToEncrypt);
413
+ const mutexKey = jid;
414
+ const node = await encryptionMutex.mutex(mutexKey, async () => {
415
+ const { type, ciphertext } = await signalRepository.encryptMessage({ jid, data: bytes });
416
+ if (type === 'pkmsg') {
417
+ shouldIncludeDeviceIdentity = true;
418
+ }
419
+ return {
420
+ tag: 'to',
421
+ attrs: { jid },
422
+ content: [
423
+ {
424
+ tag: 'enc',
425
+ attrs: { v: '2', type, ...(extraAttrs || {}) },
426
+ content: ciphertext
427
+ }
428
+ ]
429
+ };
377
430
  });
378
- if (type === 'pkmsg') {
379
- shouldIncludeDeviceIdentity = true;
380
- }
381
- return {
382
- tag: 'to',
383
- attrs: { jid },
384
- content: [
385
- {
386
- tag: 'enc',
387
- attrs: {
388
- v: '2',
389
- type,
390
- ...(extraAttrs || {})
391
- },
392
- content: ciphertext
393
- }
394
- ]
395
- };
396
- });
397
- return node;
431
+ return node;
432
+ }
433
+ catch (err) {
434
+ logger.error({ jid, err }, 'Failed to encrypt for recipient');
435
+ return null;
436
+ }
398
437
  });
399
438
  const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
439
+ if (recipientJids.length > 0 && nodes.length === 0) {
440
+ throw new Boom('All encryptions failed', { statusCode: 500 });
441
+ }
400
442
  return { nodes, shouldIncludeDeviceIdentity };
401
443
  };
402
- const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
444
+ const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, AI = false }) => {
403
445
  const meId = authState.creds.me.id;
404
446
  const meLid = authState.creds.me?.lid;
405
447
  const isRetryResend = Boolean(participant?.jid);
406
448
  let shouldIncludeDeviceIdentity = isRetryResend;
449
+ let didPushAdditional = false;
407
450
  const statusJid = 'status@broadcast';
408
451
  const { user, server } = jidDecode(jid);
409
452
  const isGroup = server === 'g.us';
453
+ const isPrivate = server === 's.whatsapp.net';
410
454
  const isStatus = jid === statusJid;
411
455
  const isLid = server === 'lid';
412
456
  const isNewsletter = server === 'newsletter';
@@ -419,6 +463,7 @@ export const makeMessagesSocket = (config) => {
419
463
  const destinationJid = !isStatus ? finalJid : statusJid;
420
464
  const binaryNodeContent = [];
421
465
  const devices = [];
466
+ let reportingMessage;
422
467
  const meMsg = {
423
468
  deviceSentMessage: {
424
469
  destinationJid,
@@ -427,6 +472,10 @@ export const makeMessagesSocket = (config) => {
427
472
  messageContextInfo: message.messageContextInfo
428
473
  };
429
474
  const extraAttrs = {};
475
+ // normalizeMessageContent BEFORE transaction — exact addons pattern
476
+ const messages = normalizeMessageContent(message) || message;
477
+ const buttonType = getButtonType(messages);
478
+ const pollMessage = messages.pollCreationMessage || messages.pollCreationMessageV2 || messages.pollCreationMessageV3;
430
479
  if (participant) {
431
480
  if (!isGroup && !isStatus) {
432
481
  additionalAttributes = { ...additionalAttributes, device_fanout: 'false' };
@@ -439,7 +488,7 @@ export const makeMessagesSocket = (config) => {
439
488
  });
440
489
  }
441
490
  await authState.keys.transaction(async () => {
442
- const mediaType = getMediaType(message);
491
+ const mediaType = getMediaType(messages);
443
492
  if (mediaType) {
444
493
  extraAttrs['mediatype'] = mediaType;
445
494
  }
@@ -448,7 +497,7 @@ export const makeMessagesSocket = (config) => {
448
497
  const bytes = encodeNewsletterMessage(patched);
449
498
  binaryNodeContent.push({
450
499
  tag: 'plaintext',
451
- attrs: {},
500
+ attrs: mediaType ? { mediatype: mediaType } : {},
452
501
  content: bytes
453
502
  });
454
503
  const stanza = {
@@ -465,7 +514,10 @@ export const makeMessagesSocket = (config) => {
465
514
  await sendNode(stanza);
466
515
  return;
467
516
  }
468
- if (normalizeMessageContent(message)?.pinInChatMessage) {
517
+ if (messages.pinInChatMessage ||
518
+ messages.keepInChatMessage ||
519
+ messages.reactionMessage ||
520
+ messages.protocolMessage?.editedMessage) {
469
521
  extraAttrs['decrypt-fail'] = 'hide'; // todo: expand for reactions and other types
470
522
  }
471
523
  if (isGroupOrStatus && !isRetryResend) {
@@ -513,6 +565,7 @@ export const makeMessagesSocket = (config) => {
513
565
  throw new Boom('Per-jid patching is not supported in groups');
514
566
  }
515
567
  const bytes = encodeWAMessage(patched);
568
+ reportingMessage = patched;
516
569
  const groupAddressingMode = additionalAttributes?.['addressing_mode'] || groupData?.addressingMode || 'lid';
517
570
  const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId;
518
571
  const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
@@ -567,6 +620,12 @@ export const makeMessagesSocket = (config) => {
567
620
  logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation');
568
621
  }
569
622
  const { user: ownUser } = jidDecode(ownId);
623
+ if (!participant) {
624
+ const patchedForReporting = await patchMessageBeforeSending(message, [jid]);
625
+ reportingMessage = Array.isArray(patchedForReporting)
626
+ ? patchedForReporting.find(item => item.recipientJid === jid) || patchedForReporting[0]
627
+ : patchedForReporting;
628
+ }
570
629
  if (!isRetryResend) {
571
630
  const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
572
631
  devices.push({
@@ -711,9 +770,52 @@ export const makeMessagesSocket = (config) => {
711
770
  });
712
771
  logger.debug({ jid }, 'adding device identity');
713
772
  }
714
- const contactTcTokenData = !isGroup && !isRetryResend && !isStatus ? await authState.keys.get('tctoken', [destinationJid]) : {};
715
- const tcTokenBuffer = contactTcTokenData[destinationJid]?.token;
716
- if (tcTokenBuffer) {
773
+ if (!isNewsletter &&
774
+ !isRetryResend &&
775
+ reportingMessage?.messageContextInfo?.messageSecret &&
776
+ shouldIncludeReportingToken(reportingMessage)) {
777
+ try {
778
+ const encoded = encodeWAMessage(reportingMessage);
779
+ const reportingKey = {
780
+ id: msgId,
781
+ fromMe: true,
782
+ remoteJid: destinationJid,
783
+ participant: participant?.jid
784
+ };
785
+ const reportingNode = await getMessageReportingToken(encoded, reportingMessage, reportingKey);
786
+ if (reportingNode) {
787
+ ;
788
+ stanza.content.push(reportingNode);
789
+ logger.trace({ jid }, 'added reporting token to message');
790
+ }
791
+ }
792
+ catch (error) {
793
+ logger.warn({ jid, trace: error?.stack }, 'failed to attach reporting token');
794
+ }
795
+ }
796
+ // WA Web never attaches tctoken to peer (AppStateSync) messages — server rejects with 479
797
+ const isPeerMessage = additionalAttributes?.['category'] === 'peer';
798
+ const is1on1Send = !isGroup && !isRetryResend && !isStatus && !isNewsletter && !isPeerMessage;
799
+ // Resolve destination to LID for tctoken storage — matches Signal session key pattern
800
+ const tcTokenJid = is1on1Send ? await resolveTcTokenJid(destinationJid, getLIDForPN) : destinationJid;
801
+ const contactTcTokenData = is1on1Send ? await authState.keys.get('tctoken', [tcTokenJid]) : {};
802
+ const existingTokenEntry = contactTcTokenData[tcTokenJid];
803
+ let tcTokenBuffer = existingTokenEntry?.token;
804
+ // Treat expired tokens the same as missing — clear from cache
805
+ if (tcTokenBuffer?.length && isTcTokenExpired(existingTokenEntry?.timestamp)) {
806
+ logger.debug({ jid: destinationJid, timestamp: existingTokenEntry?.timestamp }, 'tctoken expired, clearing');
807
+ tcTokenBuffer = undefined;
808
+ const cleared = existingTokenEntry?.senderTimestamp !== undefined
809
+ ? { token: Buffer.alloc(0), senderTimestamp: existingTokenEntry.senderTimestamp }
810
+ : null;
811
+ try {
812
+ await authState.keys.set({ tctoken: { [tcTokenJid]: cleared } });
813
+ }
814
+ catch (err) {
815
+ logger.debug({ jid: destinationJid, err: err?.message }, 'failed to persist tctoken expiry cleanup');
816
+ }
817
+ }
818
+ if (tcTokenBuffer?.length && sock.serverProps.privacyTokenOn1to1) {
717
819
  ;
718
820
  stanza.content.push({
719
821
  tag: 'tctoken',
@@ -721,12 +823,116 @@ export const makeMessagesSocket = (config) => {
721
823
  content: tcTokenBuffer
722
824
  });
723
825
  }
724
- if (additionalNodes && additionalNodes.length > 0) {
826
+ // Inject poll/event meta node directly in relayMessage
827
+ // (mirrors innovators — handles direct relayMessage calls, not just sendMessage)
828
+ if (pollMessage || messages.eventMessage) {
829
+ const hasPollMeta = (additionalNodes ?? []).some((n) => n.tag === 'meta' && ('polltype' in n.attrs || 'event_type' in n.attrs));
830
+ if (!hasPollMeta) {
831
+ const metaAttrs = messages.eventMessage
832
+ ? { event_type: 'creation' }
833
+ : isNewsletter
834
+ ? {
835
+ polltype: 'creation',
836
+ contenttype: pollMessage?.pollContentType === 2 ? 'image' : 'text'
837
+ }
838
+ : { polltype: 'creation' };
839
+ stanza.content.push({ tag: 'meta', attrs: metaAttrs });
840
+ }
841
+ }
842
+ // Inject <biz> node for button messages
843
+ // Works for: WhatsApp Messenger + WhatsApp Business, Android + iOS
844
+ if (!isJidNewsletter(destinationJid) && buttonType) {
845
+ const buttonsNode = getButtonArgs(messages);
846
+ const filteredButtons = getBinaryFilteredButtons(additionalNodes ? additionalNodes : []);
847
+ if (filteredButtons) {
848
+ ;
849
+ stanza.content.push(...additionalNodes);
850
+ didPushAdditional = true;
851
+ }
852
+ else {
853
+ ;
854
+ stanza.content.push(buttonsNode);
855
+ }
856
+ // bot node: required for buttons to be interactive in private chats
857
+ // (independent of AI flag — matches innovators + button-helper behaviour)
858
+ if (isPrivate) {
859
+ const botNode = { tag: 'bot', attrs: { biz_bot: '1' } };
860
+ const filteredBizBot = getBinaryFilteredBizBot(additionalNodes ? additionalNodes : []);
861
+ if (filteredBizBot) {
862
+ if (!didPushAdditional) {
863
+ ;
864
+ stanza.content.push(...additionalNodes);
865
+ didPushAdditional = true;
866
+ }
867
+ }
868
+ else {
869
+ ;
870
+ stanza.content.push(botNode);
871
+ }
872
+ }
873
+ }
874
+ // AI icon feature — adds bot node for non-button messages with AI flag
875
+ if (AI && isPrivate && !buttonType) {
876
+ const botNode = { tag: 'bot', attrs: { biz_bot: '1' } };
877
+ const filteredBizBot = getBinaryFilteredBizBot(additionalNodes ? additionalNodes : []);
878
+ if (filteredBizBot) {
879
+ ;
880
+ stanza.content.push(...additionalNodes);
881
+ didPushAdditional = true;
882
+ }
883
+ else {
884
+ ;
885
+ stanza.content.push(botNode);
886
+ }
887
+ }
888
+ if (!didPushAdditional && additionalNodes && additionalNodes.length > 0) {
725
889
  ;
726
890
  stanza.content.push(...additionalNodes);
727
891
  }
728
892
  logger.debug({ msgId }, `sending message to ${participants.length} devices`);
729
893
  await sendNode(stanza);
894
+ // Fire-and-forget: issue our token to the contact AFTER message send.
895
+ // WA Web skips protocol messages and PSA/bot contacts
896
+ const isProtocolMsg = !!normalizeMessageContent(message)?.protocolMessage;
897
+ const isBotOrPSA = destinationJid === PSA_WID || isJidBot(destinationJid) || isJidMetaAI(destinationJid);
898
+ if (is1on1Send &&
899
+ !isProtocolMsg &&
900
+ !isBotOrPSA &&
901
+ shouldSendNewTcToken(existingTokenEntry?.senderTimestamp) &&
902
+ !inFlightTcTokenIssuance.has(tcTokenJid)) {
903
+ inFlightTcTokenIssuance.add(tcTokenJid);
904
+ const issueTimestamp = unixTimestampSeconds();
905
+ const getPNForLID = signalRepository.lidMapping.getPNForLID.bind(signalRepository.lidMapping);
906
+ resolveIssuanceJid(destinationJid, sock.serverProps.lidTrustedTokenIssueToLid, getLIDForPN, getPNForLID)
907
+ .then(issueJid => issuePrivacyTokens([issueJid], issueTimestamp))
908
+ .then(async (result) => {
909
+ await storeTcTokensFromIqResult({
910
+ result,
911
+ fallbackJid: tcTokenJid,
912
+ keys: authState.keys,
913
+ getLIDForPN
914
+ });
915
+ const currentData = await authState.keys.get('tctoken', [tcTokenJid]);
916
+ const currentEntry = currentData[tcTokenJid];
917
+ const indexWrite = await buildMergedTcTokenIndexWrite(authState.keys, [tcTokenJid]);
918
+ await authState.keys.set({
919
+ tctoken: {
920
+ [tcTokenJid]: {
921
+ token: Buffer.alloc(0),
922
+ ...currentEntry,
923
+ senderTimestamp: issueTimestamp
924
+ },
925
+ ...indexWrite
926
+ }
927
+ });
928
+ })
929
+ .catch(err => {
930
+ logger.debug({ jid: destinationJid, err: err?.message }, 'fire-and-forget tctoken issuance failed');
931
+ })
932
+ .finally(() => {
933
+ inFlightTcTokenIssuance.delete(tcTokenJid);
934
+ });
935
+ }
730
936
  // Add message to retry cache if enabled
731
937
  if (messageRetryManager && !participant) {
732
938
  messageRetryManager.addRecentMessage(destinationJid, msgId, message);
@@ -734,66 +940,6 @@ export const makeMessagesSocket = (config) => {
734
940
  }, meId);
735
941
  return msgId;
736
942
  };
737
- const getMessageType = (message) => {
738
- if (message.pollCreationMessage || message.pollCreationMessageV2 || message.pollCreationMessageV3) {
739
- return 'poll';
740
- }
741
- if (message.eventMessage) {
742
- return 'event';
743
- }
744
- if (getMediaType(message) !== '') {
745
- return 'media';
746
- }
747
- return 'text';
748
- };
749
- const getMediaType = (message) => {
750
- if (message.imageMessage) {
751
- return 'image';
752
- }
753
- else if (message.videoMessage) {
754
- return message.videoMessage.gifPlayback ? 'gif' : 'video';
755
- }
756
- else if (message.audioMessage) {
757
- return message.audioMessage.ptt ? 'ptt' : 'audio';
758
- }
759
- else if (message.contactMessage) {
760
- return 'vcard';
761
- }
762
- else if (message.documentMessage) {
763
- return 'document';
764
- }
765
- else if (message.contactsArrayMessage) {
766
- return 'contact_array';
767
- }
768
- else if (message.liveLocationMessage) {
769
- return 'livelocation';
770
- }
771
- else if (message.stickerMessage) {
772
- return 'sticker';
773
- }
774
- else if (message.listMessage) {
775
- return 'list';
776
- }
777
- else if (message.listResponseMessage) {
778
- return 'list_response';
779
- }
780
- else if (message.buttonsResponseMessage) {
781
- return 'buttons_response';
782
- }
783
- else if (message.orderMessage) {
784
- return 'order';
785
- }
786
- else if (message.productMessage) {
787
- return 'product';
788
- }
789
- else if (message.interactiveResponseMessage) {
790
- return 'native_flow_response';
791
- }
792
- else if (message.groupInviteMessage) {
793
- return 'url';
794
- }
795
- return '';
796
- };
797
943
  const getPrivacyTokens = async (jids) => {
798
944
  const t = unixTimestampSeconds().toString();
799
945
  const result = await query({
@@ -820,11 +966,38 @@ export const makeMessagesSocket = (config) => {
820
966
  });
821
967
  return result;
822
968
  };
969
+ const issuePrivacyTokens = async (jids, timestamp) => {
970
+ const t = (timestamp ?? unixTimestampSeconds()).toString();
971
+ const result = await query({
972
+ tag: 'iq',
973
+ attrs: {
974
+ to: S_WHATSAPP_NET,
975
+ type: 'set',
976
+ xmlns: 'privacy'
977
+ },
978
+ content: [
979
+ {
980
+ tag: 'tokens',
981
+ attrs: {},
982
+ content: jids.map(jid => ({
983
+ tag: 'token',
984
+ attrs: {
985
+ jid: jidNormalizedUser(jid),
986
+ t,
987
+ type: 'trusted_contact'
988
+ }
989
+ }))
990
+ }
991
+ ]
992
+ });
993
+ return result;
994
+ };
823
995
  const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
824
996
  const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
825
997
  return {
826
998
  ...sock,
827
999
  getPrivacyTokens,
1000
+ issuePrivacyTokens,
828
1001
  assertSessions,
829
1002
  relayMessage,
830
1003
  sendReceipt,
@@ -837,11 +1010,12 @@ export const makeMessagesSocket = (config) => {
837
1010
  createParticipantNodes,
838
1011
  getUSyncDevices,
839
1012
  messageRetryManager,
1013
+ updateMemberLabel,
840
1014
  updateMediaMessage: async (message) => {
841
1015
  const content = assertMediaContent(message.message);
842
1016
  const mediaKey = content.mediaKey;
843
1017
  const meId = authState.creds.me.id;
844
- const node = await encryptMediaRetryRequest(message.key, mediaKey, meId);
1018
+ const node = encryptMediaRetryRequest(message.key, mediaKey, meId);
845
1019
  let error = undefined;
846
1020
  await Promise.all([
847
1021
  sendNode(node),
@@ -853,7 +1027,7 @@ export const makeMessagesSocket = (config) => {
853
1027
  }
854
1028
  else {
855
1029
  try {
856
- const media = await decryptMediaRetryData(result.media, mediaKey, result.key.id);
1030
+ const media = decryptMediaRetryData(result.media, mediaKey, result.key.id);
857
1031
  if (media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
858
1032
  const resultStr = proto.MediaRetryNotification.ResultType[media.result];
859
1033
  throw new Boom(`Media re-upload failed by device (${resultStr})`, {
@@ -893,6 +1067,48 @@ export const makeMessagesSocket = (config) => {
893
1067
  : disappearingMessagesInChat;
894
1068
  await groupToggleEphemeral(jid, value);
895
1069
  }
1070
+ else if (typeof content === 'object' && 'album' in content && content.album) {
1071
+ // Album message — matches addons prepareAlbumMessageContent
1072
+ const albumItems = content.album;
1073
+ const albumMsg = generateWAMessageFromContent(jid, {
1074
+ albumMessage: {
1075
+ expectedImageCount: albumItems.filter((i) => 'image' in i).length,
1076
+ expectedVideoCount: albumItems.filter((i) => 'video' in i).length
1077
+ }
1078
+ }, { userJid, ...options });
1079
+ await relayMessage(jid, albumMsg.message, { messageId: albumMsg.key.id });
1080
+ const mediaMsgs = [];
1081
+ for (const item of albumItems) {
1082
+ const mediaContent = 'image' in item ? { image: item.image, ...item } : { video: item.video, ...item };
1083
+ const mediaMsg = await generateWAMessage(jid, mediaContent, {
1084
+ logger,
1085
+ userJid,
1086
+ upload: async (encFilePath, opts) => {
1087
+ const up = await waUploadToServer(encFilePath, { ...opts, newsletter: isJidNewsletter(jid) });
1088
+ return up;
1089
+ },
1090
+ ...options
1091
+ });
1092
+ if (mediaMsg.message) {
1093
+ mediaMsg.message.messageContextInfo = {
1094
+ messageSecret: randomBytes(32),
1095
+ messageAssociation: {
1096
+ associationType: 1,
1097
+ parentMessageKey: albumMsg.key
1098
+ }
1099
+ };
1100
+ }
1101
+ mediaMsgs.push(mediaMsg);
1102
+ await delay(options.delay || 500);
1103
+ await relayMessage(jid, mediaMsg.message, {
1104
+ messageId: mediaMsg.key.id,
1105
+ useCachedGroupMetadata: options.useCachedGroupMetadata,
1106
+ statusJidList: options.statusJidList,
1107
+ AI: options.ai
1108
+ });
1109
+ }
1110
+ return mediaMsgs[0];
1111
+ }
896
1112
  else {
897
1113
  const fullMsg = await generateWAMessage(jid, content, {
898
1114
  logger,
@@ -912,7 +1128,11 @@ export const makeMessagesSocket = (config) => {
912
1128
  upload: waUploadToServer,
913
1129
  mediaCache: config.mediaCache,
914
1130
  options: config.options,
915
- messageId: generateMessageIDV2(sock.user?.id),
1131
+ messageId: (('groupStatus' in content && content.groupStatus) ||
1132
+ ('cards' in content && content?.cards)) &&
1133
+ !options.messageId
1134
+ ? `4NY4W3B${randomBytes(16).toString('hex').toUpperCase()}`
1135
+ : generateMessageIDV2(sock.user?.id),
916
1136
  ...options
917
1137
  });
918
1138
  const isEventMsg = 'event' in content && !!content.event;
@@ -939,11 +1159,16 @@ export const makeMessagesSocket = (config) => {
939
1159
  additionalAttributes.edit = '2';
940
1160
  }
941
1161
  else if (isPollMessage) {
1162
+ // Newsletter polls need a contenttype attr ('image' or 'text')
1163
+ // matching innovators behaviour for cross-client compatibility
1164
+ const pollAttrs = { polltype: 'creation' };
1165
+ if (isJidNewsletter(jid)) {
1166
+ const pollContent = content.poll;
1167
+ pollAttrs.contenttype = pollContent?.pollContentType === 2 ? 'image' : 'text';
1168
+ }
942
1169
  additionalNodes.push({
943
1170
  tag: 'meta',
944
- attrs: {
945
- polltype: 'creation'
946
- }
1171
+ attrs: pollAttrs
947
1172
  });
948
1173
  }
949
1174
  else if (isEventMsg) {
@@ -959,15 +1184,101 @@ export const makeMessagesSocket = (config) => {
959
1184
  useCachedGroupMetadata: options.useCachedGroupMetadata,
960
1185
  additionalAttributes,
961
1186
  statusJidList: options.statusJidList,
962
- additionalNodes
1187
+ additionalNodes,
1188
+ AI: options.ai
963
1189
  });
964
1190
  if (config.emitOwnEvents) {
965
1191
  process.nextTick(async () => {
966
- await processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1192
+ await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
967
1193
  });
968
1194
  }
969
1195
  return fullMsg;
970
1196
  }
1197
+ },
1198
+ // Logic lives in addons/from-messages-send.ts → execSendStatusMentions
1199
+ sendStatusMentions: async (content, jids = []) => {
1200
+ return execSendStatusMentions(content, jids, {
1201
+ meId: authState.creds.me.id,
1202
+ logger,
1203
+ groupMetadata: sock.groupMetadata,
1204
+ cachedGroupMetadata: config.cachedGroupMetadata,
1205
+ relayMessage,
1206
+ waUploadToServer,
1207
+ getUrlInfo,
1208
+ config,
1209
+ linkPreviewImageThumbnailWidth,
1210
+ generateHighQualityLinkPreview,
1211
+ httpRequestOptions
1212
+ });
1213
+ },
1214
+ /**
1215
+ * Send a rich table via botForwardedMessage → richResponseMessage.
1216
+ */
1217
+ sendTable: async (jid, title, headers, rows, quoted, options = {}) => {
1218
+ const { message, messageId } = generateTableContent(title, headers, rows, quoted, options);
1219
+ await relayMessage(jid, message, { messageId });
1220
+ return { message, messageId };
1221
+ },
1222
+ /**
1223
+ * Send a rich list (single-column table).
1224
+ */
1225
+ sendList: async (jid, title, items, quoted, options = {}) => {
1226
+ const { message, messageId } = generateListContent(title, items, quoted, options);
1227
+ await relayMessage(jid, message, { messageId });
1228
+ return { message, messageId };
1229
+ },
1230
+ /**
1231
+ * Send a syntax-highlighted code block.
1232
+ */
1233
+ sendCodeBlock: async (jid, code, quoted, options = {}) => {
1234
+ const { message, messageId } = generateCodeBlockContent(code, quoted, options);
1235
+ await relayMessage(jid, message, { messageId });
1236
+ return { message, messageId };
1237
+ },
1238
+ /**
1239
+ * Send a LaTeX expression as text (no image rendering).
1240
+ */
1241
+ sendLatex: async (jid, quoted, options) => {
1242
+ const { message, messageId } = generateLatexContent(quoted, options);
1243
+ await relayMessage(jid, message, { messageId });
1244
+ return { message, messageId };
1245
+ },
1246
+ /**
1247
+ * Render LaTeX to PNG images, upload, and send.
1248
+ */
1249
+ sendLatexImage: async (jid, quoted, options, renderLatexToPng, uploadFn) => {
1250
+ const { message, messageId } = await generateLatexImageContent(quoted, options, uploadFn, renderLatexToPng);
1251
+ await relayMessage(jid, message, { messageId });
1252
+ return { message, messageId };
1253
+ },
1254
+ /**
1255
+ * Render LaTeX to PNG inline image blocks, upload, and send.
1256
+ */
1257
+ sendLatexInlineImage: async (jid, quoted, options, renderLatexToPng, uploadFn) => {
1258
+ const { message, messageId } = await generateLatexInlineImageContent(quoted, options, uploadFn, renderLatexToPng);
1259
+ await relayMessage(jid, message, { messageId });
1260
+ return { message, messageId };
1261
+ },
1262
+ /**
1263
+ * Send a fully custom rich message from a raw submessages array.
1264
+ */
1265
+ sendRichMessage: async (jid, submessages, quoted) => {
1266
+ const { message, messageId } = generateRichMessageContent(submessages, quoted);
1267
+ await relayMessage(jid, message, { messageId });
1268
+ return { message, messageId };
1269
+ },
1270
+ /**
1271
+ * Capture the unifiedResponse payload from an incoming Meta AI message.
1272
+ * Returns null if the message is not a rich response.
1273
+ */
1274
+ extractUnifiedResponse,
1275
+ /**
1276
+ * Re-send a captured unifiedResponse to a new JID.
1277
+ */
1278
+ sendUnifiedResponse: async (jid, quoted, captured) => {
1279
+ const { message, messageId } = generateUnifiedResponseContent(quoted, captured);
1280
+ await relayMessage(jid, message, { messageId });
1281
+ return { message, messageId };
971
1282
  }
972
1283
  };
973
1284
  };