@queenanya/baileys 9.2.4 → 9.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/README.md +329 -1237
  2. package/WAProto/fix-imports.js +22 -18
  3. package/WAProto/index.js +22 -18
  4. package/lib/Defaults/index.d.ts +17 -0
  5. package/lib/Defaults/index.d.ts.map +1 -1
  6. package/lib/Defaults/index.js +29 -3
  7. package/lib/Defaults/index.js.map +1 -1
  8. package/lib/Signal/libsignal.d.ts.map +1 -1
  9. package/lib/Signal/libsignal.js +61 -2
  10. package/lib/Signal/libsignal.js.map +1 -1
  11. package/lib/Signal/lid-mapping.d.ts +5 -9
  12. package/lib/Signal/lid-mapping.d.ts.map +1 -1
  13. package/lib/Signal/lid-mapping.js +170 -70
  14. package/lib/Signal/lid-mapping.js.map +1 -1
  15. package/lib/Socket/business.d.ts +114 -2
  16. package/lib/Socket/business.d.ts.map +1 -1
  17. package/lib/Socket/chats.d.ts +14 -1
  18. package/lib/Socket/chats.d.ts.map +1 -1
  19. package/lib/Socket/chats.js +253 -38
  20. package/lib/Socket/chats.js.map +1 -1
  21. package/lib/Socket/communities.d.ts +114 -2
  22. package/lib/Socket/communities.d.ts.map +1 -1
  23. package/lib/Socket/groups.d.ts +9 -0
  24. package/lib/Socket/groups.d.ts.map +1 -1
  25. package/lib/Socket/groups.js +6 -0
  26. package/lib/Socket/groups.js.map +1 -1
  27. package/lib/Socket/index.d.ts +114 -2
  28. package/lib/Socket/index.d.ts.map +1 -1
  29. package/lib/Socket/index.js +0 -6
  30. package/lib/Socket/index.js.map +1 -1
  31. package/lib/Socket/messages-recv.d.ts +115 -3
  32. package/lib/Socket/messages-recv.d.ts.map +1 -1
  33. package/lib/Socket/messages-recv.js +739 -150
  34. package/lib/Socket/messages-recv.js.map +1 -1
  35. package/lib/Socket/messages-send.d.ts +118 -4
  36. package/lib/Socket/messages-send.d.ts.map +1 -1
  37. package/lib/Socket/messages-send.js +328 -86
  38. package/lib/Socket/messages-send.js.map +1 -1
  39. package/lib/Socket/newsletter.d.ts +9 -0
  40. package/lib/Socket/newsletter.d.ts.map +1 -1
  41. package/lib/Socket/newsletter.js +2 -2
  42. package/lib/Socket/newsletter.js.map +1 -1
  43. package/lib/Socket/socket.d.ts +2 -0
  44. package/lib/Socket/socket.d.ts.map +1 -1
  45. package/lib/Socket/socket.js +143 -17
  46. package/lib/Socket/socket.js.map +1 -1
  47. package/lib/Types/Auth.d.ts +2 -0
  48. package/lib/Types/Auth.d.ts.map +1 -1
  49. package/lib/Types/Call.d.ts +10 -1
  50. package/lib/Types/Call.d.ts.map +1 -1
  51. package/lib/Types/Contact.d.ts +2 -0
  52. package/lib/Types/Contact.d.ts.map +1 -1
  53. package/lib/Types/Events.d.ts +21 -1
  54. package/lib/Types/Events.d.ts.map +1 -1
  55. package/lib/Types/GroupMetadata.d.ts +4 -0
  56. package/lib/Types/GroupMetadata.d.ts.map +1 -1
  57. package/lib/Types/Message.d.ts +530 -16
  58. package/lib/Types/Message.d.ts.map +1 -1
  59. package/lib/Types/Message.js.map +1 -1
  60. package/lib/Types/Newsletter.d.ts +37 -31
  61. package/lib/Types/Newsletter.d.ts.map +1 -1
  62. package/lib/Types/Newsletter.js +27 -23
  63. package/lib/Types/Newsletter.js.map +1 -1
  64. package/lib/Types/State.d.ts +54 -0
  65. package/lib/Types/State.d.ts.map +1 -1
  66. package/lib/Types/State.js +42 -0
  67. package/lib/Types/State.js.map +1 -1
  68. package/lib/Types/index.d.ts +9 -0
  69. package/lib/Types/index.d.ts.map +1 -1
  70. package/lib/Types/index.js.map +1 -1
  71. package/lib/Utils/browser-utils.d.ts +13 -0
  72. package/lib/Utils/browser-utils.d.ts.map +1 -1
  73. package/lib/Utils/browser-utils.js +90 -10
  74. package/lib/Utils/browser-utils.js.map +1 -1
  75. package/lib/Utils/chat-utils.d.ts +30 -0
  76. package/lib/Utils/chat-utils.d.ts.map +1 -1
  77. package/lib/Utils/chat-utils.js +81 -52
  78. package/lib/Utils/chat-utils.js.map +1 -1
  79. package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
  80. package/lib/Utils/companion-reg-client-utils.d.ts.map +1 -0
  81. package/lib/Utils/companion-reg-client-utils.js +34 -0
  82. package/lib/Utils/companion-reg-client-utils.js.map +1 -0
  83. package/lib/Utils/crypto.d.ts +4 -8
  84. package/lib/Utils/crypto.d.ts.map +1 -1
  85. package/lib/Utils/crypto.js +2 -26
  86. package/lib/Utils/crypto.js.map +1 -1
  87. package/lib/Utils/decode-wa-message.d.ts +12 -0
  88. package/lib/Utils/decode-wa-message.d.ts.map +1 -1
  89. package/lib/Utils/decode-wa-message.js +16 -0
  90. package/lib/Utils/decode-wa-message.js.map +1 -1
  91. package/lib/Utils/event-buffer.js +10 -1
  92. package/lib/Utils/event-buffer.js.map +1 -1
  93. package/lib/Utils/generics.d.ts +3 -1
  94. package/lib/Utils/generics.d.ts.map +1 -1
  95. package/lib/Utils/generics.js +16 -3
  96. package/lib/Utils/generics.js.map +1 -1
  97. package/lib/Utils/history.d.ts +5 -2
  98. package/lib/Utils/history.d.ts.map +1 -1
  99. package/lib/Utils/history.js +53 -17
  100. package/lib/Utils/history.js.map +1 -1
  101. package/lib/Utils/identity-change-handler.d.ts +44 -0
  102. package/lib/Utils/identity-change-handler.d.ts.map +1 -0
  103. package/lib/Utils/identity-change-handler.js +50 -0
  104. package/lib/Utils/identity-change-handler.js.map +1 -0
  105. package/lib/Utils/index.d.ts +6 -0
  106. package/lib/Utils/index.d.ts.map +1 -1
  107. package/lib/Utils/index.js +6 -0
  108. package/lib/Utils/index.js.map +1 -1
  109. package/lib/Utils/interactive-message.d.ts +201 -0
  110. package/lib/Utils/interactive-message.d.ts.map +1 -0
  111. package/lib/Utils/interactive-message.js +256 -0
  112. package/lib/Utils/interactive-message.js.map +1 -0
  113. package/lib/Utils/lt-hash.d.ts +7 -12
  114. package/lib/Utils/lt-hash.d.ts.map +1 -1
  115. package/lib/Utils/lt-hash.js +2 -42
  116. package/lib/Utils/lt-hash.js.map +1 -1
  117. package/lib/Utils/message-composer.d.ts +5 -0
  118. package/lib/Utils/message-composer.d.ts.map +1 -0
  119. package/lib/Utils/message-composer.js +5 -0
  120. package/lib/Utils/message-composer.js.map +1 -0
  121. package/lib/Utils/message-retry-manager.d.ts +30 -2
  122. package/lib/Utils/message-retry-manager.d.ts.map +1 -1
  123. package/lib/Utils/message-retry-manager.js +59 -2
  124. package/lib/Utils/message-retry-manager.js.map +1 -1
  125. package/lib/Utils/messages-media.d.ts +19 -5
  126. package/lib/Utils/messages-media.d.ts.map +1 -1
  127. package/lib/Utils/messages-media.js +26 -17
  128. package/lib/Utils/messages-media.js.map +1 -1
  129. package/lib/Utils/messages.d.ts.map +1 -1
  130. package/lib/Utils/messages.js +433 -13
  131. package/lib/Utils/messages.js.map +1 -1
  132. package/lib/Utils/noise-handler.d.ts +2 -2
  133. package/lib/Utils/noise-handler.d.ts.map +1 -1
  134. package/lib/Utils/noise-handler.js +10 -10
  135. package/lib/Utils/noise-handler.js.map +1 -1
  136. package/lib/Utils/offline-node-processor.d.ts +17 -0
  137. package/lib/Utils/offline-node-processor.d.ts.map +1 -0
  138. package/lib/Utils/offline-node-processor.js +40 -0
  139. package/lib/Utils/offline-node-processor.js.map +1 -0
  140. package/lib/Utils/process-message.d.ts.map +1 -1
  141. package/lib/Utils/process-message.js +96 -16
  142. package/lib/Utils/process-message.js.map +1 -1
  143. package/lib/Utils/reporting-utils.js +2 -2
  144. package/lib/Utils/reporting-utils.js.map +1 -1
  145. package/lib/Utils/stanza-ack.d.ts +11 -0
  146. package/lib/Utils/stanza-ack.d.ts.map +1 -0
  147. package/lib/Utils/stanza-ack.js +38 -0
  148. package/lib/Utils/stanza-ack.js.map +1 -0
  149. package/lib/Utils/sync-action-utils.d.ts.map +1 -1
  150. package/lib/Utils/sync-action-utils.js +2 -1
  151. package/lib/Utils/sync-action-utils.js.map +1 -1
  152. package/lib/Utils/tc-token-utils.d.ts +26 -1
  153. package/lib/Utils/tc-token-utils.d.ts.map +1 -1
  154. package/lib/Utils/tc-token-utils.js +149 -4
  155. package/lib/Utils/tc-token-utils.js.map +1 -1
  156. package/lib/Utils/use-mongo-file-auth-state.d.ts +16 -0
  157. package/lib/Utils/use-mongo-file-auth-state.d.ts.map +1 -0
  158. package/lib/Utils/use-mongo-file-auth-state.js +60 -0
  159. package/lib/Utils/use-mongo-file-auth-state.js.map +1 -0
  160. package/lib/Utils/use-multi-file-auth-state.js +1 -1
  161. package/lib/Utils/use-multi-file-auth-state.js.map +1 -1
  162. package/lib/Utils/validate-connection.d.ts.map +1 -1
  163. package/lib/Utils/validate-connection.js +11 -1
  164. package/lib/Utils/validate-connection.js.map +1 -1
  165. package/lib/WABinary/generic-utils.d.ts +9 -0
  166. package/lib/WABinary/generic-utils.d.ts.map +1 -1
  167. package/lib/WABinary/generic-utils.js +23 -0
  168. package/lib/WABinary/generic-utils.js.map +1 -1
  169. package/lib/WABinary/jid-utils.js.map +1 -1
  170. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -1
  171. package/lib/WAUSync/Protocols/USyncContactProtocol.js +26 -3
  172. package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -1
  173. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
  174. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
  175. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
  176. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
  177. package/lib/WAUSync/Protocols/index.d.ts +1 -0
  178. package/lib/WAUSync/Protocols/index.d.ts.map +1 -1
  179. package/lib/WAUSync/Protocols/index.js +1 -0
  180. package/lib/WAUSync/Protocols/index.js.map +1 -1
  181. package/lib/WAUSync/USyncQuery.d.ts +1 -0
  182. package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
  183. package/lib/WAUSync/USyncQuery.js +5 -1
  184. package/lib/WAUSync/USyncQuery.js.map +1 -1
  185. package/lib/WAUSync/USyncUser.d.ts +4 -0
  186. package/lib/WAUSync/USyncUser.d.ts.map +1 -1
  187. package/lib/WAUSync/USyncUser.js +8 -0
  188. package/lib/WAUSync/USyncUser.js.map +1 -1
  189. package/lib/addons/anti-delete.d.ts +72 -0
  190. package/lib/addons/anti-delete.d.ts.map +1 -0
  191. package/lib/addons/anti-delete.js +165 -0
  192. package/lib/addons/anti-delete.js.map +1 -0
  193. package/lib/addons/auto-reply.d.ts +67 -0
  194. package/lib/addons/auto-reply.d.ts.map +1 -0
  195. package/lib/addons/auto-reply.js +145 -0
  196. package/lib/addons/auto-reply.js.map +1 -0
  197. package/lib/addons/browser-presets.d.ts +16 -0
  198. package/lib/addons/browser-presets.d.ts.map +1 -0
  199. package/lib/addons/browser-presets.js +24 -0
  200. package/lib/addons/browser-presets.js.map +1 -0
  201. package/lib/addons/button-sender.d.ts +260 -0
  202. package/lib/addons/button-sender.d.ts.map +1 -0
  203. package/lib/addons/button-sender.js +771 -0
  204. package/lib/addons/button-sender.js.map +1 -0
  205. package/lib/addons/call-handler.d.ts +79 -0
  206. package/lib/addons/call-handler.d.ts.map +1 -0
  207. package/lib/addons/call-handler.js +342 -0
  208. package/lib/addons/call-handler.js.map +1 -0
  209. package/lib/addons/from-chats.d.ts +30 -0
  210. package/lib/addons/from-chats.d.ts.map +1 -0
  211. package/lib/addons/from-chats.js +38 -0
  212. package/lib/addons/from-chats.js.map +1 -0
  213. package/lib/addons/from-messages-recv.d.ts +59 -0
  214. package/lib/addons/from-messages-recv.d.ts.map +1 -0
  215. package/lib/addons/from-messages-recv.js +326 -0
  216. package/lib/addons/from-messages-recv.js.map +1 -0
  217. package/lib/addons/from-messages-send.d.ts +50 -0
  218. package/lib/addons/from-messages-send.d.ts.map +1 -0
  219. package/lib/addons/from-messages-send.js +148 -0
  220. package/lib/addons/from-messages-send.js.map +1 -0
  221. package/lib/addons/from-messages.d.ts +52 -0
  222. package/lib/addons/from-messages.d.ts.map +1 -0
  223. package/lib/addons/from-messages.js +304 -0
  224. package/lib/addons/from-messages.js.map +1 -0
  225. package/lib/addons/index.d.ts +67 -0
  226. package/lib/addons/index.d.ts.map +1 -0
  227. package/lib/addons/index.js +86 -0
  228. package/lib/addons/index.js.map +1 -0
  229. package/lib/addons/interactive-message.d.ts +201 -0
  230. package/lib/addons/interactive-message.d.ts.map +1 -0
  231. package/lib/addons/interactive-message.js +256 -0
  232. package/lib/addons/interactive-message.js.map +1 -0
  233. package/lib/addons/jid-plot.d.ts +49 -0
  234. package/lib/addons/jid-plot.d.ts.map +1 -0
  235. package/lib/addons/jid-plot.js +84 -0
  236. package/lib/addons/jid-plot.js.map +1 -0
  237. package/lib/addons/jid-plotting.d.ts +54 -0
  238. package/lib/addons/jid-plotting.d.ts.map +1 -0
  239. package/lib/addons/jid-plotting.js +150 -0
  240. package/lib/addons/jid-plotting.js.map +1 -0
  241. package/lib/addons/lid-support.d.ts +41 -0
  242. package/lib/addons/lid-support.d.ts.map +1 -0
  243. package/lib/addons/lid-support.js +42 -0
  244. package/lib/addons/lid-support.js.map +1 -0
  245. package/lib/addons/message-composer.d.ts +142 -0
  246. package/lib/addons/message-composer.d.ts.map +1 -0
  247. package/lib/addons/message-composer.js +377 -0
  248. package/lib/addons/message-composer.js.map +1 -0
  249. package/lib/addons/message-scheduler.d.ts +77 -0
  250. package/lib/addons/message-scheduler.d.ts.map +1 -0
  251. package/lib/addons/message-scheduler.js +108 -0
  252. package/lib/addons/message-scheduler.js.map +1 -0
  253. package/lib/addons/message-search.d.ts +51 -0
  254. package/lib/addons/message-search.d.ts.map +1 -0
  255. package/lib/addons/message-search.js +171 -0
  256. package/lib/addons/message-search.js.map +1 -0
  257. package/lib/addons/message-utils.d.ts +88 -0
  258. package/lib/addons/message-utils.d.ts.map +1 -0
  259. package/lib/addons/message-utils.js +292 -0
  260. package/lib/addons/message-utils.js.map +1 -0
  261. package/lib/addons/outgoing-calls.d.ts +64 -0
  262. package/lib/addons/outgoing-calls.d.ts.map +1 -0
  263. package/lib/addons/outgoing-calls.js +139 -0
  264. package/lib/addons/outgoing-calls.js.map +1 -0
  265. package/lib/addons/pairing-fix.d.ts +31 -0
  266. package/lib/addons/pairing-fix.d.ts.map +1 -0
  267. package/lib/addons/pairing-fix.js +74 -0
  268. package/lib/addons/pairing-fix.js.map +1 -0
  269. package/lib/addons/past-participants.d.ts +42 -0
  270. package/lib/addons/past-participants.d.ts.map +1 -0
  271. package/lib/addons/past-participants.js +41 -0
  272. package/lib/addons/past-participants.js.map +1 -0
  273. package/lib/addons/rich-response.d.ts +111 -0
  274. package/lib/addons/rich-response.d.ts.map +1 -0
  275. package/lib/addons/rich-response.js +152 -0
  276. package/lib/addons/rich-response.js.map +1 -0
  277. package/lib/addons/scheduling.d.ts +41 -0
  278. package/lib/addons/scheduling.d.ts.map +1 -0
  279. package/lib/addons/scheduling.js +110 -0
  280. package/lib/addons/scheduling.js.map +1 -0
  281. package/lib/addons/status-posting.d.ts +177 -0
  282. package/lib/addons/status-posting.d.ts.map +1 -0
  283. package/lib/addons/status-posting.js +240 -0
  284. package/lib/addons/status-posting.js.map +1 -0
  285. package/lib/addons/stickerpack.d.ts +37 -0
  286. package/lib/addons/stickerpack.d.ts.map +1 -0
  287. package/lib/addons/stickerpack.js +39 -0
  288. package/lib/addons/stickerpack.js.map +1 -0
  289. package/lib/addons/templates.d.ts +72 -0
  290. package/lib/addons/templates.d.ts.map +1 -0
  291. package/lib/addons/templates.js +145 -0
  292. package/lib/addons/templates.js.map +1 -0
  293. package/lib/addons/vcard.d.ts +59 -0
  294. package/lib/addons/vcard.d.ts.map +1 -0
  295. package/lib/addons/vcard.js +88 -0
  296. package/lib/addons/vcard.js.map +1 -0
  297. package/lib/index.d.ts +1 -0
  298. package/lib/index.d.ts.map +1 -1
  299. package/lib/index.js +1 -0
  300. package/lib/index.js.map +1 -1
  301. package/package.json +5 -3
@@ -1,18 +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
12
  import { getMessageReportingToken, shouldIncludeReportingToken } from '../Utils/reporting-utils.js';
9
- import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidGroup, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.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';
10
15
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
11
16
  import { makeNewsletterSocket } from './newsletter.js';
12
17
  export const makeMessagesSocket = (config) => {
13
18
  const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
14
19
  const sock = makeNewsletterSocket(config);
15
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();
16
27
  const userDevicesCache = config.userDevicesCache ||
17
28
  new NodeCache({
18
29
  stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
@@ -259,6 +270,9 @@ export const makeMessagesSocket = (config) => {
259
270
  * Update Member Label
260
271
  */
261
272
  const updateMemberLabel = (jid, memberLabel) => {
273
+ if (!isJidGroup(jid)) {
274
+ throw new Error('Jid must a group jid!');
275
+ }
262
276
  return relayMessage(jid, {
263
277
  protocolMessage: {
264
278
  type: proto.Message.ProtocolMessage.Type.GROUP_MEMBER_LABEL_CHANGE,
@@ -427,14 +441,16 @@ export const makeMessagesSocket = (config) => {
427
441
  }
428
442
  return { nodes, shouldIncludeDeviceIdentity };
429
443
  };
430
- 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 }) => {
431
445
  const meId = authState.creds.me.id;
432
446
  const meLid = authState.creds.me?.lid;
433
447
  const isRetryResend = Boolean(participant?.jid);
434
448
  let shouldIncludeDeviceIdentity = isRetryResend;
449
+ let didPushAdditional = false;
435
450
  const statusJid = 'status@broadcast';
436
451
  const { user, server } = jidDecode(jid);
437
452
  const isGroup = server === 'g.us';
453
+ const isPrivate = server === 's.whatsapp.net';
438
454
  const isStatus = jid === statusJid;
439
455
  const isLid = server === 'lid';
440
456
  const isNewsletter = server === 'newsletter';
@@ -456,6 +472,10 @@ export const makeMessagesSocket = (config) => {
456
472
  messageContextInfo: message.messageContextInfo
457
473
  };
458
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;
459
479
  if (participant) {
460
480
  if (!isGroup && !isStatus) {
461
481
  additionalAttributes = { ...additionalAttributes, device_fanout: 'false' };
@@ -468,7 +488,7 @@ export const makeMessagesSocket = (config) => {
468
488
  });
469
489
  }
470
490
  await authState.keys.transaction(async () => {
471
- const mediaType = getMediaType(message);
491
+ const mediaType = getMediaType(messages);
472
492
  if (mediaType) {
473
493
  extraAttrs['mediatype'] = mediaType;
474
494
  }
@@ -477,7 +497,7 @@ export const makeMessagesSocket = (config) => {
477
497
  const bytes = encodeNewsletterMessage(patched);
478
498
  binaryNodeContent.push({
479
499
  tag: 'plaintext',
480
- attrs: {},
500
+ attrs: mediaType ? { mediatype: mediaType } : {},
481
501
  content: bytes
482
502
  });
483
503
  const stanza = {
@@ -494,7 +514,10 @@ export const makeMessagesSocket = (config) => {
494
514
  await sendNode(stanza);
495
515
  return;
496
516
  }
497
- if (normalizeMessageContent(message)?.pinInChatMessage || normalizeMessageContent(message)?.reactionMessage) {
517
+ if (messages.pinInChatMessage ||
518
+ messages.keepInChatMessage ||
519
+ messages.reactionMessage ||
520
+ messages.protocolMessage?.editedMessage) {
498
521
  extraAttrs['decrypt-fail'] = 'hide'; // todo: expand for reactions and other types
499
522
  }
500
523
  if (isGroupOrStatus && !isRetryResend) {
@@ -770,9 +793,29 @@ export const makeMessagesSocket = (config) => {
770
793
  logger.warn({ jid, trace: error?.stack }, 'failed to attach reporting token');
771
794
  }
772
795
  }
773
- const contactTcTokenData = !isGroup && !isRetryResend && !isStatus ? await authState.keys.get('tctoken', [destinationJid]) : {};
774
- const tcTokenBuffer = contactTcTokenData[destinationJid]?.token;
775
- if (tcTokenBuffer) {
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) {
776
819
  ;
777
820
  stanza.content.push({
778
821
  tag: 'tctoken',
@@ -780,12 +823,116 @@ export const makeMessagesSocket = (config) => {
780
823
  content: tcTokenBuffer
781
824
  });
782
825
  }
783
- 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) {
784
889
  ;
785
890
  stanza.content.push(...additionalNodes);
786
891
  }
787
892
  logger.debug({ msgId }, `sending message to ${participants.length} devices`);
788
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
+ }
789
936
  // Add message to retry cache if enabled
790
937
  if (messageRetryManager && !participant) {
791
938
  messageRetryManager.addRecentMessage(destinationJid, msgId, message);
@@ -793,75 +940,6 @@ export const makeMessagesSocket = (config) => {
793
940
  }, meId);
794
941
  return msgId;
795
942
  };
796
- const getMessageType = (message) => {
797
- const normalizedMessage = normalizeMessageContent(message);
798
- if (!normalizedMessage)
799
- return 'text';
800
- if (normalizedMessage.reactionMessage || normalizedMessage.encReactionMessage) {
801
- return 'reaction';
802
- }
803
- if (normalizedMessage.pollCreationMessage ||
804
- normalizedMessage.pollCreationMessageV2 ||
805
- normalizedMessage.pollCreationMessageV3 ||
806
- normalizedMessage.pollUpdateMessage) {
807
- return 'poll';
808
- }
809
- if (normalizedMessage.eventMessage) {
810
- return 'event';
811
- }
812
- if (getMediaType(normalizedMessage) !== '') {
813
- return 'media';
814
- }
815
- return 'text';
816
- };
817
- const getMediaType = (message) => {
818
- if (message.imageMessage) {
819
- return 'image';
820
- }
821
- else if (message.videoMessage) {
822
- return message.videoMessage.gifPlayback ? 'gif' : 'video';
823
- }
824
- else if (message.audioMessage) {
825
- return message.audioMessage.ptt ? 'ptt' : 'audio';
826
- }
827
- else if (message.contactMessage) {
828
- return 'vcard';
829
- }
830
- else if (message.documentMessage) {
831
- return 'document';
832
- }
833
- else if (message.contactsArrayMessage) {
834
- return 'contact_array';
835
- }
836
- else if (message.liveLocationMessage) {
837
- return 'livelocation';
838
- }
839
- else if (message.stickerMessage) {
840
- return 'sticker';
841
- }
842
- else if (message.listMessage) {
843
- return 'list';
844
- }
845
- else if (message.listResponseMessage) {
846
- return 'list_response';
847
- }
848
- else if (message.buttonsResponseMessage) {
849
- return 'buttons_response';
850
- }
851
- else if (message.orderMessage) {
852
- return 'order';
853
- }
854
- else if (message.productMessage) {
855
- return 'product';
856
- }
857
- else if (message.interactiveResponseMessage) {
858
- return 'native_flow_response';
859
- }
860
- else if (message.groupInviteMessage) {
861
- return 'url';
862
- }
863
- return '';
864
- };
865
943
  const getPrivacyTokens = async (jids) => {
866
944
  const t = unixTimestampSeconds().toString();
867
945
  const result = await query({
@@ -888,11 +966,38 @@ export const makeMessagesSocket = (config) => {
888
966
  });
889
967
  return result;
890
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
+ };
891
995
  const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
892
996
  const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
893
997
  return {
894
998
  ...sock,
895
999
  getPrivacyTokens,
1000
+ issuePrivacyTokens,
896
1001
  assertSessions,
897
1002
  relayMessage,
898
1003
  sendReceipt,
@@ -910,7 +1015,7 @@ export const makeMessagesSocket = (config) => {
910
1015
  const content = assertMediaContent(message.message);
911
1016
  const mediaKey = content.mediaKey;
912
1017
  const meId = authState.creds.me.id;
913
- const node = await encryptMediaRetryRequest(message.key, mediaKey, meId);
1018
+ const node = encryptMediaRetryRequest(message.key, mediaKey, meId);
914
1019
  let error = undefined;
915
1020
  await Promise.all([
916
1021
  sendNode(node),
@@ -922,7 +1027,7 @@ export const makeMessagesSocket = (config) => {
922
1027
  }
923
1028
  else {
924
1029
  try {
925
- const media = await decryptMediaRetryData(result.media, mediaKey, result.key.id);
1030
+ const media = decryptMediaRetryData(result.media, mediaKey, result.key.id);
926
1031
  if (media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
927
1032
  const resultStr = proto.MediaRetryNotification.ResultType[media.result];
928
1033
  throw new Boom(`Media re-upload failed by device (${resultStr})`, {
@@ -962,6 +1067,48 @@ export const makeMessagesSocket = (config) => {
962
1067
  : disappearingMessagesInChat;
963
1068
  await groupToggleEphemeral(jid, value);
964
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
+ }
965
1112
  else {
966
1113
  const fullMsg = await generateWAMessage(jid, content, {
967
1114
  logger,
@@ -981,7 +1128,11 @@ export const makeMessagesSocket = (config) => {
981
1128
  upload: waUploadToServer,
982
1129
  mediaCache: config.mediaCache,
983
1130
  options: config.options,
984
- 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),
985
1136
  ...options
986
1137
  });
987
1138
  const isEventMsg = 'event' in content && !!content.event;
@@ -1008,11 +1159,16 @@ export const makeMessagesSocket = (config) => {
1008
1159
  additionalAttributes.edit = '2';
1009
1160
  }
1010
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
+ }
1011
1169
  additionalNodes.push({
1012
1170
  tag: 'meta',
1013
- attrs: {
1014
- polltype: 'creation'
1015
- }
1171
+ attrs: pollAttrs
1016
1172
  });
1017
1173
  }
1018
1174
  else if (isEventMsg) {
@@ -1028,7 +1184,8 @@ export const makeMessagesSocket = (config) => {
1028
1184
  useCachedGroupMetadata: options.useCachedGroupMetadata,
1029
1185
  additionalAttributes,
1030
1186
  statusJidList: options.statusJidList,
1031
- additionalNodes
1187
+ additionalNodes,
1188
+ AI: options.ai
1032
1189
  });
1033
1190
  if (config.emitOwnEvents) {
1034
1191
  process.nextTick(async () => {
@@ -1037,6 +1194,91 @@ export const makeMessagesSocket = (config) => {
1037
1194
  }
1038
1195
  return fullMsg;
1039
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 };
1040
1282
  }
1041
1283
  };
1042
1284
  };