@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
@@ -3,12 +3,14 @@ import { randomBytes } from 'crypto';
3
3
  import { promises as fs } from 'fs';
4
4
  import {} from 'stream';
5
5
  import { proto } from '../../WAProto/index.js';
6
+ import { buildAdminInviteMessage, buildCallMessage, buildPaymentInviteMessage, buildStickerPackMessage } from '../addons/from-messages.js';
6
7
  import { CALL_AUDIO_PREFIX, CALL_VIDEO_PREFIX, MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
7
8
  import { WAMessageStatus, WAProto } from '../Types/index.js';
8
9
  import { isJidGroup, isJidNewsletter, isJidStatusBroadcast, jidNormalizedUser } from '../WABinary/index.js';
9
10
  import { sha256 } from './crypto.js';
10
11
  import { generateMessageIDV2, getKeyAuthor, unixTimestampSeconds } from './generics.js';
11
12
  import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, getRawMediaUploadData } from './messages-media.js';
13
+ import { shouldIncludeReportingToken } from './reporting-utils.js';
12
14
  const MIMETYPE_MAP = {
13
15
  image: 'image/jpeg',
14
16
  video: 'video/mp4',
@@ -100,19 +102,22 @@ export const prepareWAMessageMedia = async (message, options) => {
100
102
  logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
101
103
  const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger);
102
104
  const fileSha256B64 = fileSha256.toString('base64');
103
- const { mediaUrl, directPath } = await options.upload(filePath, {
105
+ const { directPath, thumbnailDirectPath, thumbnailSha256 } = await options.upload(filePath, {
104
106
  fileEncSha256B64: fileSha256B64,
105
107
  mediaType: mediaType,
106
- timeoutMs: options.mediaUploadTimeoutMs
108
+ timeoutMs: options.mediaUploadTimeoutMs,
109
+ newsletter: true
107
110
  });
108
111
  await fs.unlink(filePath);
109
112
  const obj = WAProto.Message.fromObject({
110
113
  // todo: add more support here
111
114
  [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
112
- url: mediaUrl,
115
+ // url intentionally omitted — newsletters use directPath only
113
116
  directPath,
114
117
  fileSha256,
115
118
  fileLength,
119
+ thumbnailDirectPath,
120
+ thumbnailSha256: thumbnailSha256 ? Buffer.from(thumbnailSha256, 'base64') : undefined,
116
121
  ...uploadData,
117
122
  media: undefined
118
123
  })
@@ -132,7 +137,7 @@ export const prepareWAMessageMedia = async (message, options) => {
132
137
  }
133
138
  const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
134
139
  const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
135
- const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
140
+ const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true && typeof uploadData.waveform === 'undefined';
136
141
  const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
137
142
  const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
138
143
  const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await encryptedStream(uploadData.media, options.mediaTypeOverride || mediaType, {
@@ -154,7 +159,7 @@ export const prepareWAMessageMedia = async (message, options) => {
154
159
  (async () => {
155
160
  try {
156
161
  if (requiresThumbnailComputation) {
157
- const { thumbnail, originalImageDimensions } = await generateThumbnail(originalFilePath, mediaType, options);
162
+ const { thumbnail, originalImageDimensions } = await generateThumbnail(originalFilePath, mediaType, { ...options, hdMode: !!message.hd });
158
163
  uploadData.jpegThumbnail = thumbnail;
159
164
  if (!uploadData.width && originalImageDimensions) {
160
165
  uploadData.width = originalImageDimensions.width;
@@ -259,10 +264,20 @@ export const generateForwardMessageContent = (message, forceForward) => {
259
264
  }
260
265
  return content;
261
266
  };
267
+ export const hasNonNullishProperty = (message, key) => {
268
+ return (typeof message === 'object' &&
269
+ message !== null &&
270
+ key in message &&
271
+ message[key] !== null &&
272
+ message[key] !== undefined);
273
+ };
274
+ function hasOptionalProperty(obj, key) {
275
+ return typeof obj === 'object' && obj !== null && key in obj && obj[key] !== null;
276
+ }
262
277
  export const generateWAMessageContent = async (message, options) => {
263
278
  var _a, _b;
264
279
  let m = {};
265
- if ('text' in message) {
280
+ if (hasNonNullishProperty(message, 'text')) {
266
281
  const extContent = { text: message.text };
267
282
  let urlInfo = message.linkPreview;
268
283
  if (typeof urlInfo === 'undefined') {
@@ -293,7 +308,7 @@ export const generateWAMessageContent = async (message, options) => {
293
308
  }
294
309
  m.extendedTextMessage = extContent;
295
310
  }
296
- else if ('contacts' in message) {
311
+ else if (hasNonNullishProperty(message, 'contacts')) {
297
312
  const contactLen = message.contacts.contacts.length;
298
313
  if (!contactLen) {
299
314
  throw new Boom('require atleast 1 contact', { statusCode: 400 });
@@ -305,25 +320,25 @@ export const generateWAMessageContent = async (message, options) => {
305
320
  m.contactsArrayMessage = WAProto.Message.ContactsArrayMessage.create(message.contacts);
306
321
  }
307
322
  }
308
- else if ('location' in message) {
323
+ else if (hasNonNullishProperty(message, 'location')) {
309
324
  m.locationMessage = WAProto.Message.LocationMessage.create(message.location);
310
325
  }
311
- else if ('react' in message) {
326
+ else if (hasNonNullishProperty(message, 'react')) {
312
327
  if (!message.react.senderTimestampMs) {
313
328
  message.react.senderTimestampMs = Date.now();
314
329
  }
315
330
  m.reactionMessage = WAProto.Message.ReactionMessage.create(message.react);
316
331
  }
317
- else if ('delete' in message) {
332
+ else if (hasNonNullishProperty(message, 'delete')) {
318
333
  m.protocolMessage = {
319
334
  key: message.delete,
320
335
  type: WAProto.Message.ProtocolMessage.Type.REVOKE
321
336
  };
322
337
  }
323
- else if ('forward' in message) {
338
+ else if (hasNonNullishProperty(message, 'forward')) {
324
339
  m = generateForwardMessageContent(message.forward, message.force);
325
340
  }
326
- else if ('disappearingMessagesInChat' in message) {
341
+ else if (hasNonNullishProperty(message, 'disappearingMessagesInChat')) {
327
342
  const exp = typeof message.disappearingMessagesInChat === 'boolean'
328
343
  ? message.disappearingMessagesInChat
329
344
  ? WA_DEFAULT_EPHEMERAL
@@ -331,7 +346,7 @@ export const generateWAMessageContent = async (message, options) => {
331
346
  : message.disappearingMessagesInChat;
332
347
  m = prepareDisappearingMessageSettingContent(exp);
333
348
  }
334
- else if ('groupInvite' in message) {
349
+ else if (hasNonNullishProperty(message, 'groupInvite')) {
335
350
  m.groupInviteMessage = {};
336
351
  m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode;
337
352
  m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration;
@@ -351,7 +366,7 @@ export const generateWAMessageContent = async (message, options) => {
351
366
  }
352
367
  }
353
368
  }
354
- else if ('pin' in message) {
369
+ else if (hasNonNullishProperty(message, 'pin')) {
355
370
  m.pinInChatMessage = {};
356
371
  m.messageContextInfo = {};
357
372
  m.pinInChatMessage.key = message.pin;
@@ -359,7 +374,7 @@ export const generateWAMessageContent = async (message, options) => {
359
374
  m.pinInChatMessage.senderTimestampMs = Date.now();
360
375
  m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0;
361
376
  }
362
- else if ('buttonReply' in message) {
377
+ else if (hasNonNullishProperty(message, 'buttonReply')) {
363
378
  switch (message.type) {
364
379
  case 'template':
365
380
  m.templateButtonReplyMessage = {
@@ -375,13 +390,36 @@ export const generateWAMessageContent = async (message, options) => {
375
390
  type: proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
376
391
  };
377
392
  break;
393
+ case 'list':
394
+ m.listResponseMessage = {
395
+ title: message.buttonReply.title,
396
+ description: message.buttonReply.description,
397
+ singleSelectReply: {
398
+ selectedRowId: message.buttonReply.rowId
399
+ },
400
+ listType: proto.Message.ListResponseMessage.ListType.SINGLE_SELECT
401
+ };
402
+ break;
403
+ case 'interactive':
404
+ m.interactiveResponseMessage = {
405
+ body: {
406
+ text: message.buttonReply.displayText,
407
+ format: proto.Message.InteractiveResponseMessage.Body.Format.EXTENSIONS_1
408
+ },
409
+ nativeFlowResponseMessage: {
410
+ name: message.buttonReply.nativeFlows?.name,
411
+ paramsJson: message.buttonReply.nativeFlows?.paramsJson,
412
+ version: message.buttonReply.nativeFlows?.version
413
+ }
414
+ };
415
+ break;
378
416
  }
379
417
  }
380
- else if ('ptv' in message && message.ptv) {
418
+ else if (hasOptionalProperty(message, 'ptv') && message.ptv) {
381
419
  const { videoMessage } = await prepareWAMessageMedia({ video: message.video }, options);
382
420
  m.ptvMessage = videoMessage;
383
421
  }
384
- else if ('product' in message) {
422
+ else if (hasNonNullishProperty(message, 'product')) {
385
423
  const { imageMessage } = await prepareWAMessageMedia({ image: message.product.productImage }, options);
386
424
  m.productMessage = WAProto.Message.ProductMessage.create({
387
425
  ...message,
@@ -391,10 +429,10 @@ export const generateWAMessageContent = async (message, options) => {
391
429
  }
392
430
  });
393
431
  }
394
- else if ('listReply' in message) {
432
+ else if (hasNonNullishProperty(message, 'listReply')) {
395
433
  m.listResponseMessage = { ...message.listReply };
396
434
  }
397
- else if ('event' in message) {
435
+ else if (hasNonNullishProperty(message, 'event')) {
398
436
  m.eventMessage = {};
399
437
  const startTime = Math.floor(message.event.startDate.getTime() / 1000);
400
438
  if (message.event.call && options.getCallLink) {
@@ -414,7 +452,7 @@ export const generateWAMessageContent = async (message, options) => {
414
452
  m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false;
415
453
  m.eventMessage.location = message.event.location;
416
454
  }
417
- else if ('poll' in message) {
455
+ else if (hasNonNullishProperty(message, 'poll')) {
418
456
  (_a = message.poll).selectableCount || (_a.selectableCount = 0);
419
457
  (_b = message.poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false);
420
458
  if (!Array.isArray(message.poll.values)) {
@@ -425,10 +463,13 @@ export const generateWAMessageContent = async (message, options) => {
425
463
  statusCode: 400
426
464
  });
427
465
  }
428
- m.messageContextInfo = {
429
- // encKey
430
- messageSecret: message.poll.messageSecret || randomBytes(32)
431
- };
466
+ // messageSecret must NOT be set for newsletter polls —
467
+ // newsletters handle encryption differently and a secret causes send failures
468
+ if (!options.jid || !isJidNewsletter(options.jid)) {
469
+ const providedSecret = message.poll.messageSecret;
470
+ const messageSecret = providedSecret instanceof Uint8Array && providedSecret.length === 32 ? providedSecret : randomBytes(32);
471
+ m.messageContextInfo = { messageSecret };
472
+ }
432
473
  const pollCreationMessage = {
433
474
  name: message.poll.name,
434
475
  selectableOptionsCount: message.poll.selectableCount,
@@ -449,15 +490,40 @@ export const generateWAMessageContent = async (message, options) => {
449
490
  }
450
491
  }
451
492
  }
452
- else if ('sharePhoneNumber' in message) {
493
+ else if ('adminInvite' in message && !!message.adminInvite) {
494
+ // addons/from-messages.ts → buildAdminInviteMessage
495
+ m.newsletterAdminInviteMessage = await buildAdminInviteMessage(message.adminInvite, message.contextInfo, options);
496
+ }
497
+ else if ('order' in message && !!message.order) {
498
+ // order → OrderMessage (from addons)
499
+ m.orderMessage = WAProto.Message.OrderMessage.fromObject(message.order);
500
+ }
501
+ else if ('keep' in message && !!message.keep) {
502
+ // keep → KeepInChatMessage (from addons)
503
+ const k = message.keep;
504
+ m.keepInChatMessage = {
505
+ key: k.key,
506
+ keepType: k.type ?? 1,
507
+ timestampMs: k.time ?? Date.now()
508
+ };
509
+ }
510
+ else if ('call' in message && !!message.call) {
511
+ // addons/from-messages.ts → buildCallMessage
512
+ m.scheduledCallCreationMessage = buildCallMessage(message.call);
513
+ }
514
+ else if ('paymentInvite' in message && !!message.paymentInvite) {
515
+ // addons/from-messages.ts → buildPaymentInviteMessage
516
+ m.paymentInviteMessage = buildPaymentInviteMessage(message.paymentInvite);
517
+ }
518
+ else if (hasNonNullishProperty(message, 'sharePhoneNumber')) {
453
519
  m.protocolMessage = {
454
520
  type: proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
455
521
  };
456
522
  }
457
- else if ('requestPhoneNumber' in message) {
523
+ else if (hasNonNullishProperty(message, 'requestPhoneNumber')) {
458
524
  m.requestPhoneNumberMessage = {};
459
525
  }
460
- else if ('limitSharing' in message) {
526
+ else if (hasNonNullishProperty(message, 'limitSharing')) {
461
527
  m.protocolMessage = {
462
528
  type: proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
463
529
  limitSharing: {
@@ -468,25 +534,381 @@ export const generateWAMessageContent = async (message, options) => {
468
534
  }
469
535
  };
470
536
  }
537
+ else if ('productList' in message && !!message.productList) {
538
+ // productList handled below after this block — just skip media
539
+ }
540
+ else if ('album' in message && !!message.album) {
541
+ // album handled in sendMessage — just set albumMessage header
542
+ const albumOpts = message.album;
543
+ m.albumMessage = {
544
+ expectedImageCount: albumOpts.expectedImageCount,
545
+ expectedVideoCount: albumOpts.expectedVideoCount
546
+ };
547
+ }
548
+ else if ('stickerPack' in message && !!message.stickerPack) {
549
+ // addons/from-messages.ts → buildStickerPackMessage
550
+ m.stickerPackMessage = await buildStickerPackMessage(message.stickerPack, options);
551
+ }
471
552
  else {
472
553
  m = await prepareWAMessageMedia(message, options);
473
554
  }
474
- if ('viewOnce' in message && !!message.viewOnce) {
555
+ // ── productList ListMessage with products ────────────────────────────────
556
+ if ('productList' in message && !!message.productList) {
557
+ const thumbnail = message.thumbnail
558
+ ? await generateThumbnail(message.thumbnail, 'image', {})
559
+ : null;
560
+ const listMessage = {
561
+ title: message.title,
562
+ buttonText: message.buttonText,
563
+ footerText: message.footer,
564
+ description: message.text,
565
+ productListInfo: {
566
+ productSections: message.productList,
567
+ headerImage: {
568
+ productId: message.productList[0]?.products?.[0]?.productId,
569
+ jpegThumbnail: thumbnail?.thumbnail ?? null
570
+ },
571
+ businessOwnerJid: message.businessOwnerJid
572
+ },
573
+ listType: proto.Message.ListMessage.ListType.PRODUCT_LIST
574
+ };
575
+ listMessage.contextInfo = {
576
+ ...(message.contextInfo || {}),
577
+ ...(message.mentions?.length ? { mentionedJid: message.mentions } : {}),
578
+ ...(message.mentionAll ? { nonJidMentions: 1 } : {})
579
+ };
580
+ m = { listMessage };
581
+ }
582
+ // ── sections → ListMessage (standalone if, runs independently like fork) ──
583
+ if ('sections' in message && !!message.sections) {
584
+ const listMessage = {
585
+ title: message.title,
586
+ buttonText: message.buttonText,
587
+ footerText: message.footer,
588
+ description: message.text,
589
+ sections: message.sections,
590
+ listType: proto.Message.ListMessage.ListType.SINGLE_SELECT
591
+ };
592
+ listMessage.contextInfo = {
593
+ ...(message.contextInfo || {}),
594
+ ...(message.mentions?.length ? { mentionedJid: message.mentions } : {}),
595
+ ...(message.mentionAll ? { nonJidMentions: 1 } : {})
596
+ };
597
+ m = { listMessage };
598
+ }
599
+ // ── buttons → buttonsMessage ──────────────────────────────────────────────
600
+ else if ('buttons' in message && !!message.buttons) {
601
+ const buttonsMessage = {
602
+ buttons: message.buttons.map((b) => ({
603
+ ...b,
604
+ type: proto.Message.ButtonsMessage.Button.Type.RESPONSE
605
+ }))
606
+ };
607
+ if ('text' in message) {
608
+ buttonsMessage.contentText = message.text;
609
+ buttonsMessage.headerType = proto.Message.ButtonsMessage.HeaderType.EMPTY;
610
+ }
611
+ else {
612
+ if ('caption' in message) {
613
+ buttonsMessage.contentText = message.caption;
614
+ }
615
+ const mediaType = Object.keys(m)[0]?.replace('Message', '').toUpperCase();
616
+ if (mediaType && mediaType in proto.Message.ButtonsMessage.HeaderType) {
617
+ buttonsMessage.headerType =
618
+ proto.Message.ButtonsMessage.HeaderType[mediaType];
619
+ }
620
+ Object.assign(buttonsMessage, m);
621
+ }
622
+ if ('footer' in message && !!message.footer) {
623
+ buttonsMessage.footerText = message.footer;
624
+ }
625
+ if ('title' in message && !!message.title) {
626
+ buttonsMessage.text = message.title;
627
+ buttonsMessage.headerType = proto.Message.ButtonsMessage.HeaderType.TEXT;
628
+ }
629
+ buttonsMessage.contextInfo = {
630
+ ...(message.contextInfo || {}),
631
+ ...(message.mentions?.length ? { mentionedJid: message.mentions } : {}),
632
+ ...(message.mentionAll ? { nonJidMentions: 1 } : {})
633
+ };
634
+ m = { buttonsMessage };
635
+ }
636
+ // ── templateButtons → TemplateMessage ─────────────────────────────────────
637
+ else if ('templateButtons' in message && !!message.templateButtons) {
638
+ const hydratedTemplate = {
639
+ hydratedButtons: message.templateButtons
640
+ };
641
+ if ('text' in message) {
642
+ hydratedTemplate.hydratedContentText = message.text;
643
+ }
644
+ else if ('caption' in message) {
645
+ hydratedTemplate.hydratedContentText = message.caption;
646
+ Object.assign(hydratedTemplate, m);
647
+ }
648
+ if ('footer' in message && !!message.footer) {
649
+ hydratedTemplate.hydratedFooterText = message.footer;
650
+ }
651
+ ;
652
+ hydratedTemplate.contextInfo = {
653
+ ...(message.contextInfo || {}),
654
+ ...(message.mentions?.length ? { mentionedJid: message.mentions } : {}),
655
+ ...(message.mentionAll ? { nonJidMentions: 1 } : {})
656
+ };
657
+ m = { templateMessage: { hydratedTemplate } };
658
+ }
659
+ // ── interactiveButtons → InteractiveMessage native flow (Android + iOS) ──
660
+ else if ('interactiveButtons' in message && !!message.interactiveButtons) {
661
+ const interactiveMessage = {
662
+ // FIX Bug 2: messageParamsJson: '' is required — without it iOS doesn't render buttons
663
+ nativeFlowMessage: { buttons: message.interactiveButtons, messageParamsJson: '' }
664
+ };
665
+ if ('text' in message) {
666
+ interactiveMessage.body = { text: message.text };
667
+ interactiveMessage.header = {
668
+ title: message.title,
669
+ subtitle: message.subtitle,
670
+ hasMediaAttachment: false
671
+ };
672
+ }
673
+ else if ('caption' in message) {
674
+ interactiveMessage.body = { text: message.caption ?? '' };
675
+ // FIX Bug 1: Object.assign(interactiveMessage, m) was mutating interactiveMessage
676
+ // AND spreading the whole corrupted object into header — completely broken.
677
+ // Correct fix: extract only the media fields from m and place them in header.
678
+ interactiveMessage.header = {
679
+ title: message.title,
680
+ subtitle: message.subtitle,
681
+ hasMediaAttachment: !!(m.imageMessage || m.videoMessage || m.documentMessage),
682
+ imageMessage: m.imageMessage ?? undefined,
683
+ videoMessage: m.videoMessage ?? undefined,
684
+ documentMessage: m.documentMessage ?? undefined
685
+ };
686
+ }
687
+ if ('footer' in message && !!message.footer) {
688
+ interactiveMessage.footer = { text: message.footer };
689
+ }
690
+ interactiveMessage.contextInfo = {
691
+ ...(message.contextInfo || {}),
692
+ ...(message.mentions?.length ? { mentionedJid: message.mentions } : {}),
693
+ ...(message.mentionAll ? { nonJidMentions: 1 } : {})
694
+ };
695
+ m = { interactiveMessage };
696
+ }
697
+ // ── shop → InteractiveMessage (shopStorefrontMessage) ─────────────────────
698
+ else if ('shop' in message && !!message.shop) {
699
+ const interactiveMessage = {
700
+ shopStorefrontMessage: {
701
+ surface: message.shop.surface,
702
+ id: message.shop.id
703
+ }
704
+ };
705
+ if ('text' in message) {
706
+ interactiveMessage.body = { text: message.text };
707
+ interactiveMessage.header = {
708
+ title: message.title,
709
+ subtitle: message.subtitle,
710
+ hasMediaAttachment: false
711
+ };
712
+ }
713
+ else if ('caption' in message) {
714
+ interactiveMessage.body = { text: message.caption ?? '' };
715
+ // FIX Bug 1: same Object.assign corruption as interactiveButtons — fixed
716
+ interactiveMessage.header = {
717
+ title: message.title,
718
+ subtitle: message.subtitle,
719
+ hasMediaAttachment: !!(m.imageMessage || m.videoMessage || m.documentMessage),
720
+ imageMessage: m.imageMessage ?? undefined,
721
+ videoMessage: m.videoMessage ?? undefined,
722
+ documentMessage: m.documentMessage ?? undefined
723
+ };
724
+ }
725
+ if ('footer' in message && !!message.footer) {
726
+ interactiveMessage.footer = { text: message.footer };
727
+ }
728
+ interactiveMessage.contextInfo = {
729
+ ...(message.contextInfo || {}),
730
+ ...(message.mentions?.length ? { mentionedJid: message.mentions } : {}),
731
+ ...(message.mentionAll ? { nonJidMentions: 1 } : {})
732
+ };
733
+ m = { interactiveMessage };
734
+ }
735
+ // ── collection → InteractiveMessage (collectionMessage) ───────────────────
736
+ else if ('collection' in message && !!message.collection) {
737
+ const interactiveMessage = {
738
+ collectionMessage: {
739
+ bizJid: message.collection.bizJid,
740
+ id: message.collection.id,
741
+ messageVersion: message.collection.version ?? message.collection.messageVersion
742
+ }
743
+ };
744
+ if ('text' in message) {
745
+ interactiveMessage.body = { text: message.text };
746
+ interactiveMessage.header = {
747
+ title: message.title,
748
+ subtitle: message.subtitle,
749
+ hasMediaAttachment: false
750
+ };
751
+ }
752
+ else if ('caption' in message) {
753
+ interactiveMessage.body = { text: message.caption ?? '' };
754
+ // FIX Bug 1: same Object.assign corruption — fixed
755
+ interactiveMessage.header = {
756
+ title: message.title,
757
+ subtitle: message.subtitle,
758
+ hasMediaAttachment: !!(m.imageMessage || m.videoMessage || m.documentMessage),
759
+ imageMessage: m.imageMessage ?? undefined,
760
+ videoMessage: m.videoMessage ?? undefined,
761
+ documentMessage: m.documentMessage ?? undefined
762
+ };
763
+ }
764
+ if ('footer' in message && !!message.footer) {
765
+ interactiveMessage.footer = { text: message.footer };
766
+ }
767
+ interactiveMessage.contextInfo = {
768
+ ...(message.contextInfo || {}),
769
+ ...(message.mentions?.length ? { mentionedJid: message.mentions } : {}),
770
+ ...(message.mentionAll ? { nonJidMentions: 1 } : {})
771
+ };
772
+ m = { interactiveMessage };
773
+ }
774
+ // ── cards → InteractiveMessage (carouselMessage, wrapped in viewOnce) ──────
775
+ else if ('cards' in message && !!message.cards) {
776
+ const normalizeMedia = (media) => {
777
+ if (!media)
778
+ return undefined;
779
+ if (Buffer.isBuffer(media))
780
+ return media;
781
+ if (typeof media === 'string')
782
+ return { url: media };
783
+ return media;
784
+ };
785
+ const slides = await Promise.all(message.cards.map(async (slide) => {
786
+ const { image, video, document: doc, product, title, body, footer, buttons } = slide;
787
+ let header = {};
788
+ if (product) {
789
+ const { imageMessage } = await prepareWAMessageMedia({ image: normalizeMedia(product.productImage) }, options);
790
+ header.productMessage = { product: { ...product, productImage: imageMessage } };
791
+ }
792
+ else if (image) {
793
+ const prepared = await prepareWAMessageMedia({ image: normalizeMedia(image) }, options);
794
+ if (prepared.imageMessage)
795
+ prepared.imageMessage.viewOnce = true;
796
+ header = prepared;
797
+ }
798
+ else if (video) {
799
+ const prepared = await prepareWAMessageMedia({ video: normalizeMedia(video) }, options);
800
+ if (prepared.videoMessage) {
801
+ prepared.videoMessage.viewOnce = true;
802
+ prepared.videoMessage.gifPlayback = false;
803
+ }
804
+ header = prepared;
805
+ }
806
+ else if (doc) {
807
+ const prepared = await prepareWAMessageMedia({
808
+ document: normalizeMedia(doc),
809
+ mimetype: slide.mimetype || 'application/octet-stream',
810
+ fileName: slide.fileName
811
+ }, options);
812
+ header = prepared;
813
+ }
814
+ const headerProps = {
815
+ title,
816
+ hasMediaAttachment: !!(header.imageMessage ||
817
+ header.videoMessage ||
818
+ header.documentMessage ||
819
+ header.productMessage),
820
+ ...header
821
+ };
822
+ return WAProto.Message.InteractiveMessage.create({
823
+ header: WAProto.Message.InteractiveMessage.Header.create(headerProps),
824
+ body: WAProto.Message.InteractiveMessage.Body.create({ text: body }),
825
+ footer: WAProto.Message.InteractiveMessage.Footer.create({ text: footer }),
826
+ nativeFlowMessage: WAProto.Message.InteractiveMessage.NativeFlowMessage.create({
827
+ buttons: buttons ?? []
828
+ })
829
+ });
830
+ }));
831
+ const interactiveMessage = {
832
+ carouselMessage: WAProto.Message.InteractiveMessage.CarouselMessage.create({ cards: slides })
833
+ };
834
+ if ('text' in message) {
835
+ interactiveMessage.body = WAProto.Message.InteractiveMessage.Body.create({
836
+ text: message.text ?? ''
837
+ });
838
+ interactiveMessage.header = WAProto.Message.InteractiveMessage.Header.create({
839
+ title: message.title,
840
+ subtitle: message.subtitle,
841
+ hasMediaAttachment: false
842
+ });
843
+ }
844
+ if ('footer' in message && !!message.footer) {
845
+ interactiveMessage.footer = WAProto.Message.InteractiveMessage.Footer.create({
846
+ text: message.footer ?? ''
847
+ });
848
+ }
849
+ interactiveMessage.contextInfo = {
850
+ ...(message.contextInfo || {}),
851
+ ...(message.mentions?.length ? { mentionedJid: message.mentions } : {}),
852
+ ...(message.mentionAll ? { nonJidMentions: 1 } : {})
853
+ };
854
+ // Wrap in viewOnceMessage matching innovators pattern for correct WA rendering
855
+ m = { interactiveMessage };
856
+ }
857
+ if (hasOptionalProperty(message, 'viewOnce') && !!message.viewOnce) {
475
858
  m = { viewOnceMessage: { message: m } };
476
859
  }
477
- if ('mentions' in message && message.mentions?.length) {
860
+ // ── viewOnceExt viewOnceMessageV2Extension ──────────────────────────────
861
+ if (hasOptionalProperty(message, 'viewOnceExt') && !!message.viewOnceExt) {
862
+ m = { viewOnceMessageV2Extension: { message: m } };
863
+ }
864
+ // ── groupStatus → groupStatusMessageV2 ────────────────────────────────────
865
+ if (hasOptionalProperty(message, 'groupStatus') && !!message.groupStatus) {
478
866
  const messageType = Object.keys(m)[0];
867
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
479
868
  const key = m[messageType];
480
- if ('contextInfo' in key && !!key.contextInfo) {
481
- key.contextInfo.mentionedJid = message.mentions;
869
+ if (key && 'contextInfo' in key && !!key.contextInfo) {
870
+ key.contextInfo.isGroupStatus = message.groupStatus;
871
+ }
872
+ else if (key) {
873
+ key.contextInfo = { isGroupStatus: message.groupStatus };
874
+ }
875
+ m = { groupStatusMessageV2: { message: m } };
876
+ }
877
+ // ── interactiveAsTemplate → templateMessage.interactiveMessageTemplate ────
878
+ // FIX Bug 4: was `else if` — so it was silently skipped whenever groupStatus was set.
879
+ // Must be an independent `if` so both can apply independently.
880
+ if (hasOptionalProperty(message, 'interactiveAsTemplate') && !!message.interactiveAsTemplate) {
881
+ if (!m.interactiveMessage) {
882
+ throw new Boom('Invalid message type for template', { statusCode: 400 });
883
+ }
884
+ m = {
885
+ templateMessage: {
886
+ interactiveMessageTemplate: m.interactiveMessage,
887
+ templateId: message.id || `template-${Date.now()}`
888
+ }
889
+ };
890
+ }
891
+ if ((hasOptionalProperty(message, 'mentions') && message.mentions?.length) ||
892
+ (hasOptionalProperty(message, 'mentionAll') && message.mentionAll)) {
893
+ const messageType = Object.keys(m)[0];
894
+ const key = m[messageType];
895
+ if (key && 'contextInfo' in key) {
896
+ key.contextInfo = key.contextInfo || {};
897
+ if (message.mentions?.length) {
898
+ key.contextInfo.mentionedJid = message.mentions;
899
+ }
900
+ if (message.mentionAll) {
901
+ key.contextInfo.nonJidMentions = 1;
902
+ }
482
903
  }
483
904
  else if (key) {
484
905
  key.contextInfo = {
485
- mentionedJid: message.mentions
906
+ mentionedJid: message.mentions,
907
+ nonJidMentions: message.mentionAll ? 1 : 0
486
908
  };
487
909
  }
488
910
  }
489
- if ('edit' in message) {
911
+ if (hasOptionalProperty(message, 'edit')) {
490
912
  m = {
491
913
  protocolMessage: {
492
914
  key: message.edit,
@@ -496,7 +918,7 @@ export const generateWAMessageContent = async (message, options) => {
496
918
  }
497
919
  };
498
920
  }
499
- if ('contextInfo' in message && !!message.contextInfo) {
921
+ if (hasOptionalProperty(message, 'contextInfo') && !!message.contextInfo) {
500
922
  const messageType = Object.keys(m)[0];
501
923
  const key = m[messageType];
502
924
  if ('contextInfo' in key && !!key.contextInfo) {
@@ -506,6 +928,21 @@ export const generateWAMessageContent = async (message, options) => {
506
928
  key.contextInfo = message.contextInfo;
507
929
  }
508
930
  }
931
+ if (hasOptionalProperty(message, 'albumParentKey') && !!message.albumParentKey) {
932
+ m.messageContextInfo = {
933
+ ...m.messageContextInfo,
934
+ messageAssociation: {
935
+ associationType: WAProto.MessageAssociation.AssociationType.MEDIA_ALBUM,
936
+ parentMessageKey: message.albumParentKey
937
+ }
938
+ };
939
+ }
940
+ if (shouldIncludeReportingToken(m)) {
941
+ m.messageContextInfo = m.messageContextInfo || {};
942
+ if (!m.messageContextInfo.messageSecret) {
943
+ m.messageContextInfo.messageSecret = randomBytes(32);
944
+ }
945
+ }
509
946
  return WAProto.Message.create(m);
510
947
  };
511
948
  export const generateWAMessageFromContent = (jid, message, options) => {
@@ -614,7 +1051,10 @@ export const normalizeMessageContent = (content) => {
614
1051
  message?.documentWithCaptionMessage ||
615
1052
  message?.viewOnceMessageV2 ||
616
1053
  message?.viewOnceMessageV2Extension ||
617
- message?.editedMessage);
1054
+ message?.editedMessage ||
1055
+ message?.associatedChildMessage ||
1056
+ message?.groupStatusMessage ||
1057
+ message?.groupStatusMessageV2);
618
1058
  }
619
1059
  };
620
1060
  /**