@alannxd/baileys 6.0.5 → 6.0.6

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 (234) hide show
  1. package/WAProto/fix-import.js +29 -0
  2. package/WAProto/index.js +160 -201
  3. package/engine-requirements.js +1 -1
  4. package/lib/Defaults/baileys-version.json +3 -0
  5. package/lib/Defaults/index.d.ts +15 -37
  6. package/lib/Defaults/index.js +136 -119
  7. package/lib/Defaults/phonenumber-mcc.json +223 -0
  8. package/lib/Signal/Group/ciphertext-message.d.ts +0 -1
  9. package/lib/Signal/Group/ciphertext-message.js +5 -2
  10. package/lib/Signal/Group/group-session-builder.d.ts +3 -4
  11. package/lib/Signal/Group/group-session-builder.js +41 -7
  12. package/lib/Signal/Group/group_cipher.d.ts +4 -4
  13. package/lib/Signal/Group/group_cipher.js +51 -37
  14. package/lib/Signal/Group/index.d.ts +11 -12
  15. package/lib/Signal/Group/index.js +57 -12
  16. package/lib/Signal/Group/keyhelper.d.ts +1 -2
  17. package/lib/Signal/Group/keyhelper.js +44 -7
  18. package/lib/Signal/Group/queue-job.d.ts +1 -0
  19. package/lib/Signal/Group/queue-job.js +57 -0
  20. package/lib/Signal/Group/sender-chain-key.d.ts +2 -3
  21. package/lib/Signal/Group/sender-chain-key.js +15 -7
  22. package/lib/Signal/Group/sender-key-distribution-message.d.ts +1 -2
  23. package/lib/Signal/Group/sender-key-distribution-message.js +11 -8
  24. package/lib/Signal/Group/sender-key-message.d.ts +1 -2
  25. package/lib/Signal/Group/sender-key-message.js +12 -9
  26. package/lib/Signal/Group/sender-key-name.d.ts +0 -1
  27. package/lib/Signal/Group/sender-key-name.js +5 -2
  28. package/lib/Signal/Group/sender-key-record.d.ts +2 -3
  29. package/lib/Signal/Group/sender-key-record.js +21 -9
  30. package/lib/Signal/Group/sender-key-state.d.ts +6 -7
  31. package/lib/Signal/Group/sender-key-state.js +42 -27
  32. package/lib/Signal/Group/sender-message-key.d.ts +0 -1
  33. package/lib/Signal/Group/sender-message-key.js +7 -4
  34. package/lib/Signal/libsignal.d.ts +3 -5
  35. package/lib/Signal/libsignal.js +90 -347
  36. package/lib/Socket/Client/{types.d.ts → abstract-socket-client.d.ts} +5 -4
  37. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  38. package/lib/Socket/Client/index.d.ts +3 -3
  39. package/lib/Socket/Client/index.js +19 -3
  40. package/lib/Socket/Client/mobile-socket-client.d.ts +13 -0
  41. package/lib/Socket/Client/mobile-socket-client.js +65 -0
  42. package/lib/Socket/Client/{websocket.d.ts → web-socket-client.d.ts} +2 -3
  43. package/lib/Socket/Client/web-socket-client.js +62 -0
  44. package/lib/Socket/business.d.ts +108 -154
  45. package/lib/Socket/business.js +43 -162
  46. package/lib/Socket/chats.d.ts +239 -96
  47. package/lib/Socket/chats.js +427 -627
  48. package/lib/Socket/communities.d.ts +146 -239
  49. package/lib/Socket/communities.js +80 -90
  50. package/lib/Socket/groups.d.ts +57 -104
  51. package/lib/Socket/groups.js +161 -154
  52. package/lib/Socket/index.d.ts +115 -202
  53. package/lib/Socket/index.js +10 -11
  54. package/lib/Socket/luxu.d.ts +266 -22
  55. package/lib/Socket/luxu.js +465 -422
  56. package/lib/Socket/messages-recv.d.ts +84 -136
  57. package/lib/Socket/messages-recv.js +615 -1421
  58. package/lib/Socket/messages-send.d.ts +126 -142
  59. package/lib/Socket/messages-send.js +671 -878
  60. package/lib/Socket/newsletter.d.ts +85 -121
  61. package/lib/Socket/newsletter.js +272 -147
  62. package/lib/Socket/registration.d.ts +267 -0
  63. package/lib/Socket/registration.js +166 -0
  64. package/lib/Socket/socket.d.ts +19 -34
  65. package/lib/Socket/socket.js +313 -544
  66. package/lib/Socket/usync.d.ts +36 -0
  67. package/lib/Socket/usync.js +70 -0
  68. package/lib/Store/index.d.ts +3 -10
  69. package/lib/Store/index.js +10 -10
  70. package/lib/Store/make-cache-manager-store.d.ts +11 -17
  71. package/lib/Store/make-cache-manager-store.js +41 -43
  72. package/lib/Store/make-in-memory-store.d.ts +118 -39
  73. package/lib/Store/make-in-memory-store.js +341 -112
  74. package/lib/Store/make-ordered-dictionary.d.ts +10 -11
  75. package/lib/Store/make-ordered-dictionary.js +20 -14
  76. package/lib/Store/object-repository.d.ts +9 -10
  77. package/lib/Store/object-repository.js +6 -11
  78. package/lib/Types/Auth.d.ts +12 -19
  79. package/lib/Types/Auth.js +2 -2
  80. package/lib/Types/Call.d.ts +1 -3
  81. package/lib/Types/Call.js +2 -2
  82. package/lib/Types/Chat.d.ts +13 -35
  83. package/lib/Types/Chat.js +4 -8
  84. package/lib/Types/Contact.d.ts +1 -8
  85. package/lib/Types/Contact.js +2 -2
  86. package/lib/Types/Events.d.ts +17 -116
  87. package/lib/Types/Events.js +2 -2
  88. package/lib/Types/GroupMetadata.d.ts +5 -21
  89. package/lib/Types/GroupMetadata.js +2 -2
  90. package/lib/Types/Label.d.ts +0 -12
  91. package/lib/Types/Label.js +5 -3
  92. package/lib/Types/LabelAssociation.d.ts +0 -1
  93. package/lib/Types/LabelAssociation.js +5 -3
  94. package/lib/Types/Message.d.ts +58 -105
  95. package/lib/Types/Message.js +9 -11
  96. package/lib/Types/Newsletter.d.ts +103 -0
  97. package/lib/Types/Newsletter.js +38 -0
  98. package/lib/Types/Product.d.ts +1 -2
  99. package/lib/Types/Product.js +2 -2
  100. package/lib/Types/Signal.d.ts +2 -32
  101. package/lib/Types/Signal.js +2 -2
  102. package/lib/Types/Socket.d.ts +25 -50
  103. package/lib/Types/Socket.js +2 -3
  104. package/lib/Types/State.d.ts +2 -72
  105. package/lib/Types/State.js +2 -56
  106. package/lib/Types/USync.d.ts +2 -3
  107. package/lib/Types/USync.js +2 -2
  108. package/lib/Types/index.d.ts +14 -22
  109. package/lib/Types/index.js +31 -15
  110. package/lib/Utils/auth-utils.d.ts +6 -12
  111. package/lib/Utils/auth-utils.js +143 -239
  112. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  113. package/lib/Utils/baileys-event-stream.js +63 -0
  114. package/lib/Utils/business.d.ts +2 -3
  115. package/lib/Utils/business.js +69 -66
  116. package/lib/Utils/chat-utils.d.ts +23 -52
  117. package/lib/Utils/chat-utils.js +253 -396
  118. package/lib/Utils/crypto.d.ts +22 -18
  119. package/lib/Utils/crypto.js +90 -57
  120. package/lib/Utils/decode-wa-message.d.ts +8 -55
  121. package/lib/Utils/decode-wa-message.js +84 -203
  122. package/lib/Utils/event-buffer.d.ts +8 -9
  123. package/lib/Utils/event-buffer.js +77 -185
  124. package/lib/Utils/generics.d.ts +29 -28
  125. package/lib/Utils/generics.js +210 -180
  126. package/lib/Utils/history.d.ts +9 -18
  127. package/lib/Utils/history.js +55 -93
  128. package/lib/Utils/index.d.ts +17 -22
  129. package/lib/Utils/index.js +33 -22
  130. package/lib/Utils/link-preview.d.ts +5 -5
  131. package/lib/Utils/link-preview.js +24 -16
  132. package/lib/Utils/logger.d.ts +3 -11
  133. package/lib/Utils/logger.js +7 -3
  134. package/lib/Utils/lt-hash.d.ts +12 -8
  135. package/lib/Utils/lt-hash.js +46 -3
  136. package/lib/Utils/make-mutex.d.ts +2 -4
  137. package/lib/Utils/make-mutex.js +34 -24
  138. package/lib/Utils/messages-media.d.ts +44 -61
  139. package/lib/Utils/messages-media.js +482 -451
  140. package/lib/Utils/messages.d.ts +18 -32
  141. package/lib/Utils/messages.js +369 -458
  142. package/lib/Utils/noise-handler.d.ts +14 -13
  143. package/lib/Utils/noise-handler.js +99 -145
  144. package/lib/Utils/process-message.d.ts +12 -31
  145. package/lib/Utils/process-message.js +150 -459
  146. package/lib/Utils/signal.d.ts +5 -20
  147. package/lib/Utils/signal.js +72 -120
  148. package/lib/Utils/use-multi-file-auth-state.d.ts +2 -2
  149. package/lib/Utils/use-multi-file-auth-state.js +27 -29
  150. package/lib/Utils/validate-connection.d.ts +7 -7
  151. package/lib/Utils/validate-connection.js +99 -73
  152. package/lib/WABinary/constants.d.ts +27 -25
  153. package/lib/WABinary/constants.js +20 -1281
  154. package/lib/WABinary/decode.d.ts +5 -5
  155. package/lib/WABinary/decode.js +42 -52
  156. package/lib/WABinary/encode.d.ts +3 -3
  157. package/lib/WABinary/encode.js +155 -110
  158. package/lib/WABinary/generic-utils.d.ts +7 -8
  159. package/lib/WABinary/generic-utils.js +49 -48
  160. package/lib/WABinary/index.d.ts +5 -6
  161. package/lib/WABinary/index.js +21 -6
  162. package/lib/WABinary/jid-utils.d.ts +8 -25
  163. package/lib/WABinary/jid-utils.js +40 -74
  164. package/lib/WABinary/types.d.ts +1 -2
  165. package/lib/WABinary/types.js +2 -2
  166. package/lib/WAM/BinaryInfo.d.ts +11 -3
  167. package/lib/WAM/BinaryInfo.js +5 -2
  168. package/lib/WAM/constants.d.ts +3 -5
  169. package/lib/WAM/constants.js +11958 -19461
  170. package/lib/WAM/encode.d.ts +3 -3
  171. package/lib/WAM/encode.js +22 -17
  172. package/lib/WAM/index.d.ts +3 -4
  173. package/lib/WAM/index.js +19 -4
  174. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +3 -4
  175. package/lib/WAUSync/Protocols/USyncContactProtocol.js +13 -33
  176. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +2 -3
  177. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +14 -11
  178. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +2 -3
  179. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +12 -9
  180. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +2 -3
  181. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +13 -9
  182. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +3 -4
  183. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +22 -20
  184. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +3 -5
  185. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +8 -13
  186. package/lib/WAUSync/Protocols/index.d.ts +4 -6
  187. package/lib/WAUSync/Protocols/index.js +20 -6
  188. package/lib/WAUSync/USyncQuery.d.ts +4 -6
  189. package/lib/WAUSync/USyncQuery.js +35 -44
  190. package/lib/WAUSync/USyncUser.d.ts +5 -10
  191. package/lib/WAUSync/USyncUser.js +5 -10
  192. package/lib/WAUSync/index.js +19 -4
  193. package/lib/index.d.ts +9 -10
  194. package/lib/index.js +34 -12
  195. package/package.json +50 -83
  196. package/WAProto/GenerateStatics.sh +0 -3
  197. package/WAProto/WAProto.proto +0 -5479
  198. package/WAProto/fix-imports.js +0 -85
  199. package/WAProto/index.d.ts +0 -14017
  200. package/lib/Signal/lid-mapping.d.ts +0 -23
  201. package/lib/Signal/lid-mapping.js +0 -277
  202. package/lib/Socket/Client/types.js +0 -11
  203. package/lib/Socket/Client/websocket.js +0 -54
  204. package/lib/Socket/mex.d.ts +0 -3
  205. package/lib/Socket/mex.js +0 -42
  206. package/lib/Store/keyed-db.d.ts +0 -22
  207. package/lib/Store/keyed-db.js +0 -108
  208. package/lib/Types/Bussines.d.ts +0 -25
  209. package/lib/Types/Bussines.js +0 -2
  210. package/lib/Types/Mex.d.ts +0 -141
  211. package/lib/Types/Mex.js +0 -37
  212. package/lib/Utils/browser-utils.d.ts +0 -4
  213. package/lib/Utils/browser-utils.js +0 -28
  214. package/lib/Utils/companion-reg-client-utils.d.ts +0 -17
  215. package/lib/Utils/companion-reg-client-utils.js +0 -35
  216. package/lib/Utils/identity-change-handler.d.ts +0 -44
  217. package/lib/Utils/identity-change-handler.js +0 -50
  218. package/lib/Utils/message-retry-manager.d.ts +0 -115
  219. package/lib/Utils/message-retry-manager.js +0 -265
  220. package/lib/Utils/offline-node-processor.d.ts +0 -17
  221. package/lib/Utils/offline-node-processor.js +0 -40
  222. package/lib/Utils/pre-key-manager.d.ts +0 -28
  223. package/lib/Utils/pre-key-manager.js +0 -106
  224. package/lib/Utils/reporting-utils.d.ts +0 -11
  225. package/lib/Utils/reporting-utils.js +0 -258
  226. package/lib/Utils/stanza-ack.d.ts +0 -11
  227. package/lib/Utils/stanza-ack.js +0 -38
  228. package/lib/Utils/sync-action-utils.d.ts +0 -19
  229. package/lib/Utils/sync-action-utils.js +0 -49
  230. package/lib/Utils/tc-token-utils.d.ts +0 -37
  231. package/lib/Utils/tc-token-utils.js +0 -163
  232. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +0 -10
  233. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +0 -25
  234. package/lib/WAUSync/index.d.ts +0 -4
@@ -1,70 +1,75 @@
1
- import NodeCache from '@cacheable/node-cache';
2
- import { Boom } from '@hapi/boom';
3
- import { proto } from '../../WAProto/index.js';
4
- import { DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
5
- import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, decryptMediaRetryData, DEF_MEDIA_HOST, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
6
- import { getUrlInfo } from '../Utils/link-preview.js';
7
- import { makeKeyedMutex, makeMutex } from '../Utils/make-mutex.js';
8
- import { getMessageReportingToken, shouldIncludeReportingToken } from '../Utils/reporting-utils.js';
9
- import { buildMergedTcTokenIndexWrite, isTcTokenExpired, resolveIssuanceJid, resolveTcTokenJid, shouldSendNewTcToken, storeTcTokensFromIqResult } from '../Utils/tc-token-utils.js';
10
- import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidBot, isJidGroup, isJidMetaAI, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, PSA_WID, S_WHATSAPP_NET, getAdditionalNode, getBinaryNodeFilter } from '../WABinary/index.js';
11
- import { USyncQuery, USyncUser } from '../WAUSync/index.js';
12
- import { makeNewsletterSocket } from './newsletter.js';
13
- import imup from './luxu.js';
14
- import * as Utils_1 from '../Utils/index.js';
15
- export const makeMessagesSocket = (config) => {
16
- const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount, aiLabel } = config;
17
- const sock = makeNewsletterSocket(config);
18
- const { ev, authState, messageMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral, registerSocketEndHandler } = sock;
19
- const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
20
- /**
21
- * Set of tctoken storage JIDs with a fire-and-forget `issuePrivacyTokens` IQ in flight.
22
- * Prevents duplicate IQs from rapid back-to-back sends before `senderTimestamp` persists.
23
- * Entries are always removed in `.finally()`, so the set is bounded by concurrency.
24
- */
25
- const inFlightTcTokenIssuance = new Set();
26
- const userDevicesCache = config.userDevicesCache ||
27
- new NodeCache({
28
- stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
29
- useClones: false
30
- });
31
- /** Serializes writes to userDevicesCache across USync refresh and device-notification handling. */
32
- const devicesMutex = makeMutex();
33
- // Initialize message retry manager if enabled
34
- const messageRetryManager = enableRecentMessageCache ? new MessageRetryManager(logger, maxMsgRetryCount) : null;
35
- // Prevent race conditions in Signal session encryption by user
36
- const encryptionMutex = makeKeyedMutex();
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.makeMessagesSocket = void 0;
7
+ const boom_1 = require("@hapi/boom");
8
+ const node_cache_1 = __importDefault(require("node-cache"));
9
+ const WAProto_1 = require("../../WAProto");
10
+ const Defaults_1 = require("../Defaults");
11
+ const axios_1 = require("axios")
12
+ const Types_1 = require("../Types")
13
+ const Utils_1 = require("../Utils");
14
+ const link_preview_1 = require("../Utils/link-preview");
15
+ const WABinary_1 = require("../WABinary");
16
+ const communities_1 = require("./communities");
17
+ const WAUSync_1 = require("../WAUSync");
18
+ const crypto = require("crypto");
19
+ const imup = require('./luxu');
20
+ var ListType = WAProto_1.proto.Message.ListMessage.ListType;
21
+ const makeMessagesSocket = (config) => {
22
+ const {
23
+ logger,
24
+ linkPreviewImageThumbnailWidth,
25
+ generateHighQualityLinkPreview,
26
+ options: axiosOptions,
27
+ patchMessageBeforeSending
28
+ } = config;
29
+ const sock = (0, communities_1.makeCommunitiesSocket)(config);
30
+ const {
31
+ ev,
32
+ authState,
33
+ processingMutex,
34
+ signalRepository,
35
+ upsertMessage,
36
+ query,
37
+ fetchPrivacySettings,
38
+ generateMessageTag,
39
+ sendNode,
40
+ groupMetadata,
41
+ groupToggleEphemeral,
42
+ executeUSyncQuery
43
+ } = sock;
44
+ const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
45
+ stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
46
+ useClones: false
47
+ });
37
48
  let mediaConn;
38
- /** Per-socket media host; updated whenever media_conn is fetched. Defaults to the public WhatsApp host. */
39
- let mediaHost = DEF_MEDIA_HOST;
40
49
  const refreshMediaConn = async (forceGet = false) => {
41
50
  const media = await mediaConn;
42
- if (!media || forceGet || new Date().getTime() - media.fetchDate.getTime() > media.ttl * 1000) {
51
+ if (!media || forceGet || (new Date().getTime() - media.fetchDate.getTime()) > media.ttl * 1000) {
43
52
  mediaConn = (async () => {
44
53
  const result = await query({
45
54
  tag: 'iq',
46
55
  attrs: {
47
56
  type: 'set',
48
57
  xmlns: 'w:m',
49
- to: S_WHATSAPP_NET
58
+ to: WABinary_1.S_WHATSAPP_NET,
50
59
  },
51
60
  content: [{ tag: 'media_conn', attrs: {} }]
52
61
  });
53
- const mediaConnNode = getBinaryNodeChild(result, 'media_conn');
54
- // TODO: explore full length of data that whatsapp provides
62
+ const mediaConnNode = WABinary_1.getBinaryNodeChild(result, 'media_conn');
55
63
  const node = {
56
- hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
64
+ hosts: WABinary_1.getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
57
65
  hostname: attrs.hostname,
58
- maxContentLengthBytes: +attrs.maxContentLengthBytes
66
+ maxContentLengthBytes: +attrs.maxContentLengthBytes,
59
67
  })),
60
68
  auth: mediaConnNode.attrs.auth,
61
69
  ttl: +mediaConnNode.attrs.ttl,
62
70
  fetchDate: new Date()
63
71
  };
64
72
  logger.debug('fetched media conn');
65
- if (node.hosts[0]) {
66
- mediaHost = node.hosts[0].hostname;
67
- }
68
73
  return node;
69
74
  })();
70
75
  }
@@ -75,20 +80,17 @@ export const makeMessagesSocket = (config) => {
75
80
  * used for receipts of phone call, read, delivery etc.
76
81
  * */
77
82
  const sendReceipt = async (jid, participant, messageIds, type) => {
78
- if (!messageIds || messageIds.length === 0) {
79
- throw new Boom('missing ids in receipt');
80
- }
81
83
  const node = {
82
84
  tag: 'receipt',
83
85
  attrs: {
84
- id: messageIds[0]
85
- }
86
+ id: messageIds[0],
87
+ },
86
88
  };
87
89
  const isReadReceipt = type === 'read' || type === 'read-self';
88
90
  if (isReadReceipt) {
89
- node.attrs.t = unixTimestampSeconds().toString();
91
+ node.attrs.t = (0, Utils_1.unixTimestampSeconds)().toString();
90
92
  }
91
- if (type === 'sender' && (isPnUser(jid) || isLidUser(jid))) {
93
+ if (type === 'sender' && WABinary_1.isJidUser(jid)) {
92
94
  node.attrs.recipient = jid;
93
95
  node.attrs.to = participant;
94
96
  }
@@ -99,7 +101,7 @@ export const makeMessagesSocket = (config) => {
99
101
  }
100
102
  }
101
103
  if (type) {
102
- node.attrs.type = type;
104
+ node.attrs.type = WABinary_1.isJidNewsLetter(jid) ? 'read-self' : type;
103
105
  }
104
106
  const remainingMessageIds = messageIds.slice(1);
105
107
  if (remainingMessageIds.length) {
@@ -119,7 +121,7 @@ export const makeMessagesSocket = (config) => {
119
121
  };
120
122
  /** Correctly bulk send receipts to multiple chats, participants */
121
123
  const sendReceipts = async (keys, type) => {
122
- const recps = aggregateMessageKeysNotFromMe(keys);
124
+ const recps = (0, Utils_1.aggregateMessageKeysNotFromMe)(keys);
123
125
  for (const { jid, participant, messageIds } of recps) {
124
126
  await sendReceipt(jid, participant, messageIds, type);
125
127
  }
@@ -133,450 +135,290 @@ export const makeMessagesSocket = (config) => {
133
135
  };
134
136
  /** Fetch all the devices we've to send a message to */
135
137
  const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
136
- const deviceResults = [];
138
+ const deviceResults = []
139
+
137
140
  if (!useCache) {
138
- logger.debug('not using cache for devices');
141
+ logger.debug('not using cache for devices')
139
142
  }
140
- const toFetch = [];
141
- const jidsWithUser = jids
142
- .map(jid => {
143
- const decoded = jidDecode(jid);
144
- const user = decoded?.user;
145
- const device = decoded?.device;
146
- const isExplicitDevice = typeof device === 'number' && device >= 0;
147
- if (isExplicitDevice && user) {
148
- deviceResults.push({
149
- user,
150
- device,
151
- jid
152
- });
153
- return null;
154
- }
155
- jid = jidNormalizedUser(jid);
156
- return { jid, user };
157
- })
158
- .filter(jid => jid !== null);
159
- let mgetDevices;
160
- if (useCache && userDevicesCache.mget) {
161
- const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean);
162
- mgetDevices = await userDevicesCache.mget(usersToFetch);
163
- }
164
- for (const { jid, user } of jidsWithUser) {
143
+
144
+ const toFetch = []
145
+
146
+ jids = Array.from(new Set(jids))
147
+
148
+ for (let jid of jids) {
149
+ const user = WABinary_1.jidDecode(jid)?.user
150
+
151
+ jid = WABinary_1.jidNormalizedUser(jid)
152
+
165
153
  if (useCache) {
166
- const devices = mgetDevices?.[user] ||
167
- (userDevicesCache.mget ? undefined : (await userDevicesCache.get(user)));
154
+ const devices = userDevicesCache.get(user)
155
+
168
156
  if (devices) {
169
- const devicesWithJid = devices.map(d => ({
170
- ...d,
171
- jid: jidEncode(d.user, d.server, d.device)
172
- }));
173
- deviceResults.push(...devicesWithJid);
174
- logger.trace({ user }, 'using cache for devices');
157
+ deviceResults.push(...devices)
158
+ logger.trace({ user }, 'using cache for devices')
175
159
  }
160
+
176
161
  else {
177
- toFetch.push(jid);
162
+ toFetch.push(jid)
178
163
  }
179
164
  }
165
+
180
166
  else {
181
- toFetch.push(jid);
167
+ toFetch.push(jid)
182
168
  }
183
169
  }
170
+
184
171
  if (!toFetch.length) {
185
- return deviceResults;
186
- }
187
- const requestedLidUsers = new Set();
188
- for (const jid of toFetch) {
189
- if (isLidUser(jid) || isHostedLidUser(jid)) {
190
- const user = jidDecode(jid)?.user;
191
- if (user)
192
- requestedLidUsers.add(user);
193
- }
172
+ return deviceResults
194
173
  }
195
- const query = new USyncQuery().withContext('message').withDeviceProtocol().withLIDProtocol();
174
+
175
+ const query = new WAUSync_1.USyncQuery()
176
+ .withContext('message')
177
+ .withDeviceProtocol()
178
+
196
179
  for (const jid of toFetch) {
197
- query.withUser(new USyncUser().withId(jid)); // todo: investigate - the idea here is that <user> should have an inline lid field with the lid being the pn equivalent
180
+ query.withUser(new WAUSync_1.USyncUser().withId(jid))
198
181
  }
199
- const result = await sock.executeUSyncQuery(query);
182
+
183
+ const result = await executeUSyncQuery(query)
184
+
200
185
  if (result) {
201
- // TODO: LID MAP this stuff (lid protocol will now return lid with devices)
202
- const lidResults = result.list.filter(a => !!a.lid);
203
- if (lidResults.length > 0) {
204
- logger.trace('Storing LID maps from device call');
205
- await signalRepository.lidMapping.storeLIDPNMappings(lidResults.map(a => ({ lid: a.lid, pn: a.id })));
206
- // Force-refresh sessions for newly mapped LIDs to align identity addressing
207
- try {
208
- const lids = lidResults.map(a => a.lid);
209
- if (lids.length) {
210
- await assertSessions(lids, true);
211
- }
212
- }
213
- catch (e) {
214
- logger.warn({ e, count: lidResults.length }, 'failed to assert sessions for newly mapped LIDs');
215
- }
216
- }
217
- const extracted = extractDeviceJids(result?.list, authState.creds.me.id, authState.creds.me.lid, ignoreZeroDevices);
218
- const deviceMap = {};
186
+ const extracted = Utils_1.extractDeviceJids(result?.list, authState.creds.me.id, ignoreZeroDevices)
187
+ const deviceMap = {}
188
+
219
189
  for (const item of extracted) {
220
- deviceMap[item.user] = deviceMap[item.user] || [];
221
- deviceMap[item.user]?.push(item);
190
+ deviceMap[item.user] = deviceMap[item.user] || []
191
+ deviceMap[item.user].push(item)
192
+ deviceResults.push(item)
222
193
  }
223
- // Process each user's devices as a group for bulk LID migration
224
- for (const [user, userDevices] of Object.entries(deviceMap)) {
225
- const isLidUser = requestedLidUsers.has(user);
226
- // Process all devices for this user
227
- for (const item of userDevices) {
228
- const finalJid = isLidUser
229
- ? jidEncode(user, item.server, item.device)
230
- : jidEncode(item.user, item.server, item.device);
231
- deviceResults.push({
232
- ...item,
233
- jid: finalJid
234
- });
235
- logger.debug({
236
- user: item.user,
237
- device: item.device,
238
- finalJid,
239
- usedLid: isLidUser
240
- }, 'Processed device with LID priority');
241
- }
242
- }
243
- await devicesMutex.mutex(async () => {
244
- if (userDevicesCache.mset) {
245
- // if the cache supports mset, we can set all devices in one go
246
- await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })));
247
- }
248
- else {
249
- for (const key in deviceMap) {
250
- if (deviceMap[key])
251
- await userDevicesCache.set(key, deviceMap[key]);
252
- }
253
- }
254
- });
255
- const userDeviceUpdates = {};
256
- for (const [userId, devices] of Object.entries(deviceMap)) {
257
- if (devices && devices.length > 0) {
258
- userDeviceUpdates[userId] = devices.map(d => d.device?.toString() || '0');
259
- }
260
- }
261
- if (Object.keys(userDeviceUpdates).length > 0) {
262
- try {
263
- await authState.keys.set({ 'device-list': userDeviceUpdates });
264
- logger.debug({ userCount: Object.keys(userDeviceUpdates).length }, 'stored user device lists for bulk migration');
265
- }
266
- catch (error) {
267
- logger.warn({ error }, 'failed to store user device lists');
268
- }
194
+
195
+ for (const key in deviceMap) {
196
+ userDevicesCache.set(key, deviceMap[key])
269
197
  }
270
198
  }
271
- return deviceResults;
272
- };
273
- /**
274
- * Update Member Label
275
- */
276
- const updateMemberLabel = (jid, memberLabel) => {
277
- return relayMessage(jid, {
278
- protocolMessage: {
279
- type: proto.Message.ProtocolMessage.Type.GROUP_MEMBER_LABEL_CHANGE,
280
- memberLabel: {
281
- label: memberLabel?.slice(0, 30),
282
- labelTimestamp: unixTimestampSeconds()
283
- }
284
- }
285
- }, {
286
- additionalNodes: [
287
- {
288
- tag: 'meta',
289
- attrs: {
290
- tag_reason: 'user_update',
291
- appdata: 'member_tag'
292
- },
293
- content: undefined
294
- }
295
- ]
296
- });
297
- };
199
+
200
+ return deviceResults
201
+ }
298
202
  const assertSessions = async (jids, force) => {
299
203
  let didFetchNewSession = false;
300
- const uniqueJids = [...new Set(jids)];
301
- const jidsRequiringFetch = [];
302
- logger.debug({ jids }, 'assertSessions call with jids');
303
- for (const jid of uniqueJids) {
304
- if (!force) {
305
- const sessionValidation = await signalRepository.validateSession(jid);
306
- if (sessionValidation.exists) {
307
- continue;
204
+ let jidsRequiringFetch = [];
205
+ if (force) {
206
+ jidsRequiringFetch = jids;
207
+ }
208
+ else {
209
+ const addrs = jids.map(jid => (signalRepository
210
+ .jidToSignalProtocolAddress(jid)));
211
+ const sessions = await authState.keys.get('session', addrs);
212
+ for (const jid of jids) {
213
+ const signalId = signalRepository
214
+ .jidToSignalProtocolAddress(jid);
215
+ if (!sessions[signalId]) {
216
+ jidsRequiringFetch.push(jid);
308
217
  }
309
218
  }
310
- jidsRequiringFetch.push(jid);
311
219
  }
312
220
  if (jidsRequiringFetch.length) {
313
- // LID if mapped, otherwise original
314
- const wireJids = [
315
- ...jidsRequiringFetch.filter(jid => !!isLidUser(jid) || !!isHostedLidUser(jid)),
316
- ...((await signalRepository.lidMapping.getLIDsForPNs(jidsRequiringFetch.filter(jid => !!isPnUser(jid) || !!isHostedPnUser(jid)))) || []).map(a => a.lid)
317
- ];
318
- logger.debug({ jidsRequiringFetch, wireJids }, 'fetching sessions');
221
+ logger.debug({ jidsRequiringFetch }, 'fetching sessions');
319
222
  const result = await query({
320
223
  tag: 'iq',
321
224
  attrs: {
322
225
  xmlns: 'encrypt',
323
226
  type: 'get',
324
- to: S_WHATSAPP_NET
227
+ to: WABinary_1.S_WHATSAPP_NET,
325
228
  },
326
229
  content: [
327
230
  {
328
231
  tag: 'key',
329
232
  attrs: {},
330
- content: wireJids.map(jid => {
331
- const attrs = { jid };
332
- if (force)
333
- attrs.reason = 'identity';
334
- return { tag: 'user', attrs };
335
- })
233
+ content: jidsRequiringFetch.map(jid => ({
234
+ tag: 'user',
235
+ attrs: { jid },
236
+ }))
336
237
  }
337
238
  ]
338
239
  });
339
- await parseAndInjectE2ESessions(result, signalRepository);
240
+ await (0, Utils_1.parseAndInjectE2ESessions)(result, signalRepository);
340
241
  didFetchNewSession = true;
341
242
  }
342
243
  return didFetchNewSession;
343
244
  };
245
+
246
+
344
247
  const sendPeerDataOperationMessage = async (pdoMessage) => {
345
- //TODO: for later, abstract the logic to send a Peer Message instead of just PDO - useful for App State Key Resync with phone
346
248
  if (!authState.creds.me?.id) {
347
- throw new Boom('Not authenticated');
249
+ throw new boom_1.Boom('Not authenticated')
348
250
  }
251
+
349
252
  const protocolMessage = {
350
253
  protocolMessage: {
351
254
  peerDataOperationRequestMessage: pdoMessage,
352
- type: proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
255
+ type: WAProto_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
353
256
  }
354
257
  };
355
- const meJid = jidNormalizedUser(authState.creds.me.id);
258
+ const meJid = WABinary_1.jidNormalizedUser(authState.creds.me.id);
356
259
  const msgId = await relayMessage(meJid, protocolMessage, {
357
260
  additionalAttributes: {
358
261
  category: 'peer',
359
- push_priority: 'high_force'
262
+ // eslint-disable-next-line camelcase
263
+ push_priority: 'high_force',
360
264
  },
361
- additionalNodes: [
362
- {
363
- tag: 'meta',
364
- attrs: { appdata: 'default' }
365
- }
366
- ]
367
265
  });
368
266
  return msgId;
369
267
  };
370
- const createParticipantNodes = async (recipientJids, message, extraAttrs, dsmMessage) => {
371
- if (!recipientJids.length) {
372
- return { nodes: [], shouldIncludeDeviceIdentity: false };
373
- }
374
- const patched = await patchMessageBeforeSending(message, recipientJids);
375
- const patchedMessages = Array.isArray(patched)
376
- ? patched
377
- : recipientJids.map(jid => ({ recipientJid: jid, message: patched }));
268
+ const createParticipantNodes = async (jids, message, extraAttrs) => {
269
+ const patched = await patchMessageBeforeSending(message, jids);
270
+ const bytes = (0, Utils_1.encodeWAMessage)(patched);
378
271
  let shouldIncludeDeviceIdentity = false;
379
- const meId = authState.creds.me.id;
380
- const meLid = authState.creds.me?.lid;
381
- const meLidUser = meLid ? jidDecode(meLid)?.user : null;
382
- const encryptionPromises = patchedMessages.map(async ({ recipientJid: jid, message: patchedMessage }) => {
383
- try {
384
- if (!jid)
385
- return null;
386
- let msgToEncrypt = patchedMessage;
387
- if (dsmMessage) {
388
- const { user: targetUser } = jidDecode(jid);
389
- const { user: ownPnUser } = jidDecode(meId);
390
- const ownLidUser = meLidUser;
391
- const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
392
- const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
393
- if (isOwnUser && !isExactSenderDevice) {
394
- msgToEncrypt = dsmMessage;
395
- logger.debug({ jid, targetUser }, 'Using DSM for own device');
396
- }
397
- }
398
- const bytes = encodeWAMessage(msgToEncrypt);
399
- const mutexKey = jid;
400
- const node = await encryptionMutex.mutex(mutexKey, async () => {
401
- const { type, ciphertext } = await signalRepository.encryptMessage({ jid, data: bytes });
402
- if (type === 'pkmsg') {
403
- shouldIncludeDeviceIdentity = true;
404
- }
405
- return {
406
- tag: 'to',
407
- attrs: { jid },
408
- content: [
409
- {
410
- tag: 'enc',
411
- attrs: { v: '2', type, ...(extraAttrs || {}) },
412
- content: ciphertext
413
- }
414
- ]
415
- };
416
- });
417
- return node;
418
- }
419
- catch (err) {
420
- logger.error({ jid, err }, 'Failed to encrypt for recipient');
421
- return null;
272
+ const nodes = await Promise.all(jids.map(async (jid) => {
273
+ const { type, ciphertext } = await signalRepository
274
+ .encryptMessage({ jid, data: bytes });
275
+ if (type === 'pkmsg') {
276
+ shouldIncludeDeviceIdentity = true;
422
277
  }
423
- });
424
- const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
425
- if (recipientJids.length > 0 && nodes.length === 0) {
426
- throw new Boom('All encryptions failed', { statusCode: 500 });
427
- }
278
+ const node = {
279
+ tag: 'to',
280
+ attrs: { jid },
281
+ content: [{
282
+ tag: 'enc',
283
+ attrs: {
284
+ v: '2',
285
+ type,
286
+ ...extraAttrs || {}
287
+ },
288
+ content: ciphertext
289
+ }]
290
+ };
291
+ return node;
292
+ }));
428
293
  return { nodes, shouldIncludeDeviceIdentity };
429
294
  };
430
- const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
431
- const meId = assertMeId(authState.creds);
432
- const meLid = authState.creds.me?.lid;
433
- const isRetryResend = Boolean(participant?.jid);
434
- let shouldIncludeDeviceIdentity = isRetryResend;
295
+
296
+ const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, cachedGroupMetadata, useCachedGroupMetadata, statusJidList, AI = true }) => {
297
+ const meId = authState.creds.me.id;
298
+ let shouldIncludeDeviceIdentity = false;
299
+ let didPushAdditional = false
300
+ const { user, server } = WABinary_1.jidDecode(jid);
435
301
  const statusJid = 'status@broadcast';
436
- const { user, server } = jidDecode(jid);
437
302
  const isGroup = server === 'g.us';
438
303
  const isStatus = jid === statusJid;
439
304
  const isLid = server === 'lid';
305
+ const isPrivate = server === 's.whatsapp.net'
440
306
  const isNewsletter = server === 'newsletter';
441
- const isGroupOrStatus = isGroup || isStatus;
442
- const finalJid = jid;
443
- msgId = msgId || generateMessageIDV2(meId);
307
+ msgId = msgId || (0, Utils_1.generateMessageID)();
444
308
  useUserDevicesCache = useUserDevicesCache !== false;
445
- useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
309
+ useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
446
310
  const participants = [];
447
- const destinationJid = !isStatus ? finalJid : statusJid;
311
+ const destinationJid = (!isStatus) ? WABinary_1.jidEncode(user, isLid ? 'lid' : isGroup ? 'g.us' : isNewsletter ? 'newsletter' : 's.whatsapp.net') : statusJid;
448
312
  const binaryNodeContent = [];
449
313
  const devices = [];
450
- const buttonType = getButtonType(message);
451
- let didPushAdditional = false;
452
- let reportingMessage;
453
314
  const meMsg = {
454
315
  deviceSentMessage: {
455
316
  destinationJid,
456
317
  message
457
- },
458
- messageContextInfo: message.messageContextInfo
318
+ }
459
319
  };
460
- const extraAttrs = {};
320
+ const extraAttrs = {}
321
+ const messages = Utils_1.normalizeMessageContent(message)
322
+ const buttonType = getButtonType(messages);
461
323
  if (participant) {
324
+ // when the retry request is not for a group
325
+ // only send to the specific device that asked for a retry
326
+ // otherwise the message is sent out to every device that should be a recipient
462
327
  if (!isGroup && !isStatus) {
463
- additionalAttributes = { ...additionalAttributes, device_fanout: 'false' };
328
+ additionalAttributes = { ...additionalAttributes, 'device_fanout': 'false' };
464
329
  }
465
- const { user, device } = jidDecode(participant.jid);
466
- devices.push({
467
- user,
468
- device,
469
- jid: participant.jid
470
- });
330
+ const { user, device } = WABinary_1.jidDecode(participant.jid);
331
+ devices.push({ user, device });
471
332
  }
472
333
  await authState.keys.transaction(async () => {
473
- const mediaType = getMediaType(message);
334
+ const mediaType = getMediaType(messages);
335
+
474
336
  if (mediaType) {
475
- extraAttrs['mediatype'] = mediaType;
476
- }
477
- if (isNewsletter) {
478
- const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
479
- const bytes = encodeNewsletterMessage(patched);
480
- binaryNodeContent.push({
481
- tag: 'plaintext',
482
- attrs: {},
483
- content: bytes
484
- });
485
- const stanza = {
486
- tag: 'message',
487
- attrs: {
488
- to: jid,
489
- id: msgId,
490
- type: getMessageType(message),
491
- ...(additionalAttributes || {})
492
- },
493
- content: binaryNodeContent
494
- };
495
- logger.debug({ msgId }, `sending newsletter message to ${jid}`);
496
- await sendNode(stanza);
497
- return;
337
+ extraAttrs['mediatype'] = mediaType
498
338
  }
499
- if (normalizeMessageContent(message)?.pinInChatMessage || normalizeMessageContent(message)?.reactionMessage) {
500
- extraAttrs['decrypt-fail'] = 'hide'; // todo: expand for reactions and other types
339
+
340
+ if (messages.pinInChatMessage || messages.keepInChatMessage || message.reactionMessage || message.protocolMessage?.editedMessage) {
341
+ extraAttrs['decrypt-fail'] = 'hide'
342
+ }
343
+
344
+ if (messages.interactiveResponseMessage?.nativeFlowResponseMessage) {
345
+ extraAttrs['native_flow_name'] = messages.interactiveResponseMessage?.nativeFlowResponseMessage.name
501
346
  }
502
- if (isGroupOrStatus && !isRetryResend) {
347
+
348
+ if (isGroup || isStatus) {
503
349
  const [groupData, senderKeyMap] = await Promise.all([
504
350
  (async () => {
505
- let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined; // todo: should we rely on the cache specially if the cache is outdated and the metadata has new fields?
506
- if (groupData && Array.isArray(groupData?.participants)) {
351
+ let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined
352
+ if (groupData) {
507
353
  logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata');
508
354
  }
355
+
509
356
  else if (!isStatus) {
510
- groupData = await groupMetadata(jid); // TODO: start storing group participant list + addr mode in Signal & stop relying on this
357
+ groupData = await groupMetadata(jid)
511
358
  }
359
+
512
360
  return groupData;
513
361
  })(),
514
362
  (async () => {
515
363
  if (!participant && !isStatus) {
516
- // what if sender memory is less accurate than the cached metadata
517
- // on participant change in group, we should do sender memory manipulation
518
- const result = await authState.keys.get('sender-key-memory', [jid]); // TODO: check out what if the sender key memory doesn't include the LID stuff now?
519
- return result[jid] || {};
364
+ const result = await authState.keys.get('sender-key-memory', [jid])
365
+ return result[jid] || {}
520
366
  }
521
- return {};
522
- })()
367
+
368
+ return {}
369
+
370
+ })()
523
371
  ]);
524
- const participantsList = groupData ? groupData.participants.map(p => p.id) : [];
525
- if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
526
- additionalAttributes = {
527
- ...additionalAttributes,
528
- expiration: groupData.ephemeralDuration.toString()
529
- };
530
- }
531
- if (isStatus && statusJidList) {
532
- participantsList.push(...statusJidList);
533
- }
534
- const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false);
535
- devices.push(...additionalDevices);
536
- if (isGroup) {
537
- additionalAttributes = {
538
- ...additionalAttributes,
539
- addressing_mode: groupData?.addressingMode || 'lid'
540
- };
541
- }
542
- const patched = await patchMessageBeforeSending(message);
543
- if (Array.isArray(patched)) {
544
- throw new Boom('Per-jid patching is not supported in groups');
372
+ if (!participant) {
373
+ const participantsList = (groupData && !isStatus) ? groupData.participants.map(p => p.id) : []
374
+
375
+ if (isStatus && statusJidList) {
376
+ participantsList.push(...statusJidList)
377
+ }
378
+
379
+ // if (!isStatus) {
380
+ // const expiration = await getEphemeralGroup(jid)
381
+ // additionalAttributes = {
382
+ // ...additionalAttributes,
383
+ // addressing_mode: 'pn',
384
+ // ...expiration ? { expiration: expiration.toString() } : null
385
+ // }
386
+ // }
387
+
388
+ const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false)
389
+ devices.push(...additionalDevices)
545
390
  }
546
- const bytes = encodeWAMessage(patched);
547
- reportingMessage = patched;
548
- const groupAddressingMode = additionalAttributes?.['addressing_mode'] || groupData?.addressingMode || 'lid';
549
- const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId;
391
+
392
+ const patched = await patchMessageBeforeSending(message, devices.map(d => WABinary_1.jidEncode(d.user, isLid ? 'lid' : 's.whatsapp.net', d.device)));
393
+ const bytes = Utils_1.encodeWAMessage(patched);
394
+
550
395
  const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
551
396
  group: destinationJid,
552
397
  data: bytes,
553
- meId: groupSenderIdentity
398
+ meId,
554
399
  });
555
- const senderKeyRecipients = [];
556
- for (const device of devices) {
557
- const deviceJid = device.jid;
558
- const hasKey = !!senderKeyMap[deviceJid];
559
- if ((!hasKey || !!participant) &&
560
- !isHostedLidUser(deviceJid) &&
561
- !isHostedPnUser(deviceJid) &&
562
- device.device !== 99) {
563
- //todo: revamp all this logic
564
- // the goal is to follow with what I said above for each group, and instead of a true false map of ids, we can set an array full of those the app has already sent pkmsgs
565
- senderKeyRecipients.push(deviceJid);
566
- senderKeyMap[deviceJid] = true;
400
+ const senderKeyJids = [];
401
+
402
+ for (const { user, device } of devices) {
403
+ const jid = WABinary_1.jidEncode(user, (groupData === null || groupData === void 0 ? void 0 : groupData.addressingMode) === 'lid' ? 'lid' : 's.whatsapp.net', device);
404
+ if (!senderKeyMap[jid] || !!participant) {
405
+ senderKeyJids.push(jid);
406
+ // store that this person has had the sender keys sent to them
407
+ senderKeyMap[jid] = true;
567
408
  }
568
409
  }
569
- if (senderKeyRecipients.length) {
570
- logger.debug({ senderKeyJids: senderKeyRecipients }, 'sending new sender key');
410
+ // if there are some participants with whom the session has not been established
411
+ // if there are, we re-send the senderkey
412
+ if (senderKeyJids.length) {
413
+ logger.debug({ senderKeyJids }, 'sending new sender key');
571
414
  const senderKeyMsg = {
572
415
  senderKeyDistributionMessage: {
573
416
  axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
574
417
  groupId: destinationJid
575
418
  }
576
419
  };
577
- const senderKeySessionTargets = senderKeyRecipients;
578
- await assertSessions(senderKeySessionTargets);
579
- const result = await createParticipantNodes(senderKeyRecipients, senderKeyMsg, extraAttrs);
420
+ await assertSessions(senderKeyJids, false);
421
+ const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, extraAttrs)
580
422
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
581
423
  participants.push(...result.nodes);
582
424
  }
@@ -587,177 +429,104 @@ export const makeMessagesSocket = (config) => {
587
429
  });
588
430
  await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
589
431
  }
590
- else {
591
- // ADDRESSING CONSISTENCY: Match own identity to conversation context
592
- // TODO: investigate if this is true
593
- let ownId = meId;
594
- if (isLid && meLid) {
595
- ownId = meLid;
596
- logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation');
432
+ else if (isNewsletter) {
433
+ // Message edit
434
+ if (message.protocolMessage?.editedMessage) {
435
+ msgId = message.protocolMessage.key?.id
436
+ message = message.protocolMessage.editedMessage
597
437
  }
598
- else {
599
- logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation');
438
+
439
+ // Message delete
440
+ if (message.protocolMessage?.type === WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE) {
441
+ msgId = message.protocolMessage.key?.id
442
+ message = {}
600
443
  }
601
- const { user: ownUser } = jidDecode(ownId);
444
+
445
+ const patched = await patchMessageBeforeSending(message, [])
446
+ const bytes = Utils_1.encodeNewsletterMessage(patched)
447
+
448
+ binaryNodeContent.push({
449
+ tag: 'plaintext',
450
+ attrs: extraAttrs ? extraAttrs : {},
451
+ content: bytes
452
+ })
453
+ }
454
+ else {
455
+ const { user: meUser } = WABinary_1.jidDecode(meId);
602
456
  if (!participant) {
603
- const patchedForReporting = await patchMessageBeforeSending(message, [jid]);
604
- reportingMessage = Array.isArray(patchedForReporting)
605
- ? patchedForReporting.find(item => item.recipientJid === jid) || patchedForReporting[0]
606
- : patchedForReporting;
607
- }
608
- if (!isRetryResend) {
609
- const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
610
- devices.push({
611
- user,
612
- device: 0,
613
- jid: jidEncode(user, targetUserServer, 0) // rajeh, todo: this entire logic is convoluted and weird.
614
- });
615
- if (user !== ownUser) {
616
- const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
617
- const ownUserForAddressing = isLid && meLid ? jidDecode(meLid).user : jidDecode(meId).user;
618
- devices.push({
619
- user: ownUserForAddressing,
620
- device: 0,
621
- jid: jidEncode(ownUserForAddressing, ownUserServer, 0)
622
- });
457
+ devices.push({ user })
458
+ if (user !== meUser) {
459
+ devices.push({ user: meUser })
623
460
  }
461
+
624
462
  if (additionalAttributes?.['category'] !== 'peer') {
625
- // Clear placeholders and enumerate actual devices
626
- devices.length = 0;
627
- // Use conversation-appropriate sender identity
628
- const senderIdentity = isLid && meLid
629
- ? jidEncode(jidDecode(meLid)?.user, 'lid', undefined)
630
- : jidEncode(jidDecode(meId)?.user, 's.whatsapp.net', undefined);
631
- // Enumerate devices for sender and target with consistent addressing
632
- const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false);
633
- devices.push(...sessionDevices);
634
- logger.debug({
635
- deviceCount: devices.length,
636
- devices: devices.map(d => `${d.user}:${d.device}@${jidDecode(d.jid)?.server}`)
637
- }, 'Device enumeration complete with unified addressing');
463
+ const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true)
464
+
465
+ devices.push(...additionalDevices)
638
466
  }
639
467
  }
640
- const allRecipients = [];
641
- const meRecipients = [];
642
- const otherRecipients = [];
643
- const { user: mePnUser } = jidDecode(meId);
644
- const { user: meLidUser } = meLid ? jidDecode(meLid) : { user: null };
645
- for (const { user, jid } of devices) {
646
- const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
647
- if (isExactSenderDevice) {
648
- logger.debug({ jid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)');
649
- continue;
650
- }
651
- // Check if this is our device (could match either PN or LID user)
652
- const isMe = user === mePnUser || user === meLidUser;
468
+ const allJids = [];
469
+ const meJids = [];
470
+ const otherJids = [];
471
+ for (const { user, device } of devices) {
472
+ const isMe = user === meUser
473
+ const jid = WABinary_1.jidEncode(isMe && isLid ? authState.creds?.me?.lid?.split(':')[0] || user : user, isLid ? 'lid' : 's.whatsapp.net', device)
474
+
653
475
  if (isMe) {
654
- meRecipients.push(jid);
476
+ meJids.push(jid)
655
477
  }
478
+
656
479
  else {
657
- otherRecipients.push(jid);
480
+ otherJids.push(jid)
658
481
  }
659
- allRecipients.push(jid);
482
+
483
+ allJids.push(jid)
660
484
  }
661
- await assertSessions(allRecipients);
485
+ await assertSessions(allJids, false);
662
486
  const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
663
- // For own devices: use DSM if available (1:1 chats only)
664
- createParticipantNodes(meRecipients, meMsg || message, extraAttrs),
665
- createParticipantNodes(otherRecipients, message, extraAttrs, meMsg)
666
- ]);
487
+ createParticipantNodes(meJids, meMsg, extraAttrs),
488
+ createParticipantNodes(otherJids, message, extraAttrs)
489
+ ])
667
490
  participants.push(...meNodes);
668
491
  participants.push(...otherNodes);
669
- if (meRecipients.length > 0 || otherRecipients.length > 0) {
670
- extraAttrs['phash'] = generateParticipantHashV2([...meRecipients, ...otherRecipients]);
671
- }
672
492
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
673
493
  }
674
- if (isRetryResend) {
675
- const isParticipantLid = isLidUser(participant.jid);
676
- const isMe = areJidsSameUser(participant.jid, isParticipantLid ? meLid : meId);
677
- let messageToSend = message;
678
- if (isGroupOrStatus) {
679
- let groupSenderIdentity;
680
- if (meLid && (await signalRepository.hasSenderKey({ group: destinationJid, meId: meLid }))) {
681
- groupSenderIdentity = meLid;
682
- }
683
- else if (await signalRepository.hasSenderKey({ group: destinationJid, meId })) {
684
- groupSenderIdentity = meId;
685
- }
686
- if (groupSenderIdentity) {
687
- try {
688
- const skdm = await signalRepository.getSenderKeyDistributionMessage({
689
- group: destinationJid,
690
- meId: groupSenderIdentity
691
- });
692
- messageToSend = {
693
- ...message,
694
- senderKeyDistributionMessage: {
695
- groupId: destinationJid,
696
- axolotlSenderKeyDistributionMessage: skdm
697
- }
698
- };
699
- }
700
- catch (err) {
701
- logger.warn({ err, jid: destinationJid }, 'failed to build SKDM for retry, sending without it');
702
- }
703
- }
704
- }
705
- const encodedMessageToSend = isMe
706
- ? encodeWAMessage({
707
- deviceSentMessage: {
708
- destinationJid,
709
- message: messageToSend
710
- }
711
- })
712
- : encodeWAMessage(messageToSend);
713
- const { type, ciphertext: encryptedContent } = await signalRepository.encryptMessage({
714
- data: encodedMessageToSend,
715
- jid: participant.jid
716
- });
717
- binaryNodeContent.push({
718
- tag: 'enc',
719
- attrs: {
720
- v: '2',
721
- type,
722
- count: participant.count.toString()
723
- },
724
- content: encryptedContent
725
- });
726
- }
727
494
  if (participants.length) {
728
495
  if (additionalAttributes?.['category'] === 'peer') {
729
- const peerNode = participants[0]?.content?.[0];
496
+ const peerNode = participants[0]?.content?.[0]
497
+
730
498
  if (peerNode) {
731
- binaryNodeContent.push(peerNode); // push only enc
499
+ binaryNodeContent.push(peerNode) // push only enc
732
500
  }
733
501
  }
502
+
734
503
  else {
735
504
  binaryNodeContent.push({
736
505
  tag: 'participants',
737
506
  attrs: {},
738
507
  content: participants
739
- });
508
+ })
740
509
  }
741
510
  }
511
+
742
512
  const stanza = {
743
513
  tag: 'message',
744
514
  attrs: {
745
515
  id: msgId,
746
- to: destinationJid,
747
- type: getMessageType(message),
516
+ type: getTypeMessage(messages),
748
517
  ...(additionalAttributes || {})
749
518
  },
750
519
  content: binaryNodeContent
751
- };
520
+ }
752
521
  // if the participant to send to is explicitly specified (generally retry recp)
753
522
  // ensure the message is only sent to that person
754
523
  // if a retry receipt is sent to everyone -- it'll fail decryption for everyone else who received the msg
755
524
  if (participant) {
756
- if (isJidGroup(destinationJid)) {
525
+ if (WABinary_1.isJidGroup(destinationJid)) {
757
526
  stanza.attrs.to = destinationJid;
758
527
  stanza.attrs.participant = participant.jid;
759
528
  }
760
- else if (areJidsSameUser(participant.jid, meId)) {
529
+ else if (WABinary_1.areJidsSameUser(participant.jid, meId)) {
761
530
  stanza.attrs.to = participant.jid;
762
531
  stanza.attrs.recipient = destinationJid;
763
532
  }
@@ -769,221 +538,170 @@ export const makeMessagesSocket = (config) => {
769
538
  stanza.attrs.to = destinationJid;
770
539
  }
771
540
  if (shouldIncludeDeviceIdentity) {
772
- ;
773
541
  stanza.content.push({
774
542
  tag: 'device-identity',
775
543
  attrs: {},
776
- content: encodeSignedDeviceIdentity(authState.creds.account, true)
544
+ content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
777
545
  });
778
546
  logger.debug({ jid }, 'adding device identity');
779
547
  }
780
- if (!isNewsletter && buttonType && !isStatus) {
781
- const content = getAdditionalNode(buttonType)
782
- const filteredNode = getBinaryNodeFilter(additionalNodes)
783
-
784
- if (filteredNode) {
785
- didPushAdditional = true
786
- stanza.content.push(...additionalNodes)
787
- }
788
- else {
789
- stanza.content.push(...content)
790
- }
791
- logger.debug({ jid }, 'adding business node')
792
- }
793
- if (!isNewsletter && !isGroupOrStatus && aiLabel) {
548
+
549
+ if (AI && isPrivate) {
794
550
  const botNode = {
795
551
  tag: 'bot',
796
552
  attrs: {
797
553
  biz_bot: '1'
798
554
  }
799
555
  }
800
- const filteredBizBot = getBinaryNodeFilter(additionalNodes ? additionalNodes : [])
556
+
557
+ const filteredBizBot = WABinary_1.getBinaryNodeFilter(additionalNodes ? additionalNodes : [])
558
+
801
559
  if (filteredBizBot) {
802
560
  stanza.content.push(...additionalNodes)
803
561
  didPushAdditional = true
804
562
  }
563
+
805
564
  else {
806
565
  stanza.content.push(botNode)
807
566
  }
808
567
  }
809
- if (!isNewsletter &&
810
- !isRetryResend &&
811
- reportingMessage?.messageContextInfo?.messageSecret &&
812
- shouldIncludeReportingToken(reportingMessage)) {
813
- try {
814
- const encoded = encodeWAMessage(reportingMessage);
815
- const reportingKey = {
816
- id: msgId,
817
- fromMe: true,
818
- remoteJid: destinationJid,
819
- participant: participant?.jid
820
- };
821
- const reportingNode = await getMessageReportingToken(encoded, reportingMessage, reportingKey);
822
- if (reportingNode) {
823
- ;
824
- stanza.content.push(reportingNode);
825
- logger.trace({ jid }, 'added reporting token to message');
826
- }
827
- }
828
- catch (error) {
829
- logger.warn({ jid, trace: error?.stack }, 'failed to attach reporting token');
830
- }
831
- }
832
- // WA Web never attaches tctoken to peer (AppStateSync) messages — server rejects with 479
833
- const isPeerMessage = additionalAttributes?.['category'] === 'peer';
834
- const is1on1Send = !isGroup && !isRetryResend && !isStatus && !isNewsletter && !isPeerMessage;
835
- // Resolve destination to LID for tctoken storage — matches Signal session key pattern
836
- const tcTokenJid = is1on1Send ? await resolveTcTokenJid(destinationJid, getLIDForPN) : destinationJid;
837
- const contactTcTokenData = is1on1Send ? await authState.keys.get('tctoken', [tcTokenJid]) : {};
838
- const existingTokenEntry = contactTcTokenData[tcTokenJid];
839
- let tcTokenBuffer = existingTokenEntry?.token;
840
- // Treat expired tokens the same as missing — clear from cache
841
- if (tcTokenBuffer?.length && isTcTokenExpired(existingTokenEntry?.timestamp)) {
842
- logger.debug({ jid: destinationJid, timestamp: existingTokenEntry?.timestamp }, 'tctoken expired, clearing');
843
- tcTokenBuffer = undefined;
844
- // Preserve senderTimestamp so the fire-and-forget issuance dedupe survives cleanup.
845
- const cleared = existingTokenEntry?.senderTimestamp !== undefined
846
- ? { token: Buffer.alloc(0), senderTimestamp: existingTokenEntry.senderTimestamp }
847
- : null;
848
- try {
849
- await authState.keys.set({ tctoken: { [tcTokenJid]: cleared } });
850
- }
851
- catch (err) {
852
- logger.debug({ jid: destinationJid, err: err?.message }, 'failed to persist tctoken expiry cleanup');
568
+
569
+ if(!isNewsletter && buttonType && !isStatus) {
570
+ const content = WABinary_1.getAdditionalNode(buttonType)
571
+ const filteredNode = WABinary_1.getBinaryNodeFilter(additionalNodes)
572
+
573
+ if (filteredNode) {
574
+ didPushAdditional = true
575
+ stanza.content.push(...additionalNodes)
576
+ }
577
+ else {
578
+ stanza.content.push(...content)
853
579
  }
854
- }
855
- if (tcTokenBuffer?.length && sock.serverProps.privacyTokenOn1to1) {
856
- ;
857
- stanza.content.push({
858
- tag: 'tctoken',
859
- attrs: {},
860
- content: tcTokenBuffer
861
- });
862
- }
580
+ logger.debug({ jid }, 'adding business node')
581
+ }
582
+
863
583
  if (!didPushAdditional && additionalNodes && additionalNodes.length > 0) {
864
- ;
865
584
  stanza.content.push(...additionalNodes);
866
585
  }
586
+
867
587
  logger.debug({ msgId }, `sending message to ${participants.length} devices`);
868
588
  await sendNode(stanza);
869
- // Fire-and-forget: issue our token to the contact AFTER message send.
870
- // WA Web skips protocol messages and PSA/bot contacts (TcTokenChatAction: isRegularUser)
871
- const isProtocolMsg = !!normalizeMessageContent(message)?.protocolMessage;
872
- const isBotOrPSA = destinationJid === PSA_WID || isJidBot(destinationJid) || isJidMetaAI(destinationJid);
873
- if (is1on1Send &&
874
- !isProtocolMsg &&
875
- !isBotOrPSA &&
876
- shouldSendNewTcToken(existingTokenEntry?.senderTimestamp) &&
877
- !inFlightTcTokenIssuance.has(tcTokenJid)) {
878
- inFlightTcTokenIssuance.add(tcTokenJid);
879
- const issueTimestamp = unixTimestampSeconds();
880
- const getPNForLID = signalRepository.lidMapping.getPNForLID.bind(signalRepository.lidMapping);
881
- resolveIssuanceJid(destinationJid, sock.serverProps.lidTrustedTokenIssueToLid, getLIDForPN, getPNForLID)
882
- .then(issueJid => issuePrivacyTokens([issueJid], issueTimestamp))
883
- .then(async (result) => {
884
- await storeTcTokensFromIqResult({
885
- result,
886
- fallbackJid: tcTokenJid,
887
- keys: authState.keys,
888
- getLIDForPN
889
- });
890
- const currentData = await authState.keys.get('tctoken', [tcTokenJid]);
891
- const currentEntry = currentData[tcTokenJid];
892
- const indexWrite = await buildMergedTcTokenIndexWrite(authState.keys, [tcTokenJid]);
893
- await authState.keys.set({
894
- tctoken: {
895
- [tcTokenJid]: {
896
- token: Buffer.alloc(0),
897
- ...currentEntry,
898
- senderTimestamp: issueTimestamp
899
- },
900
- ...indexWrite
901
- }
902
- });
903
- })
904
- .catch(err => {
905
- logger.debug({ jid: destinationJid, err: err?.message }, 'fire-and-forget tctoken issuance failed');
906
- })
907
- .finally(() => {
908
- inFlightTcTokenIssuance.delete(tcTokenJid);
909
- });
910
- }
911
- // Add message to retry cache if enabled
912
- if (messageRetryManager && !participant) {
913
- messageRetryManager.addRecentMessage(destinationJid, msgId, message);
914
- }
915
- }, meId);
589
+ });
916
590
  return msgId;
917
591
  };
918
- const getMessageType = (message) => {
919
- const normalizedMessage = normalizeMessageContent(message);
920
- if (!normalizedMessage)
921
- return 'text';
922
- if (normalizedMessage.reactionMessage || normalizedMessage.encReactionMessage) {
923
- return 'reaction';
924
- }
925
- if (normalizedMessage.pollCreationMessage ||
926
- normalizedMessage.pollCreationMessageV2 ||
927
- normalizedMessage.pollCreationMessageV3 ||
928
- normalizedMessage.pollUpdateMessage) {
929
- return 'poll';
930
- }
931
- if (normalizedMessage.eventMessage) {
932
- return 'event';
933
- }
934
- if (getMediaType(normalizedMessage) !== '') {
935
- return 'media';
592
+
593
+ const sendMessageMembers = async (jid, message, options = {}) => {
594
+ const {
595
+ messageId: idm,
596
+ quoted,
597
+ delayMs = 1500,
598
+ useUserDevicesCache = true,
599
+ cachedGroupMetadata
600
+ } = options;
601
+
602
+ const { server } = WABinary_1.jidDecode(jid);
603
+ if (server !== "g.us") throw new Error("@g.us server required");
604
+
605
+ const meId = authState.creds.me.id;
606
+ const messages = Utils_1.normalizeMessageContent(message);
607
+ const groupData = cachedGroupMetadata? await cachedGroupMetadata(jid) : await groupMetadata(jid);
608
+ const isLid = groupData.addressingMode === "lid";
609
+ const participantJids = groupData.participants.map(p => p.id);
610
+
611
+ logger.info(`Sending message to ${participantJids.length} members from ${jid}`);
612
+
613
+ for (let i = 0; i < participantJids.length; i++) {
614
+ const jid = participantJids[i];
615
+ if (WABinary_1.areJidsSameUser(jid, meId)) continue;
616
+
617
+ try {
618
+ const msgId = `${idm || Utils_1.generateMessageID()}_${i}`;
619
+ const fullMsg = await Utils_1.generateWAMessageFromContent(jid, message, {
620
+ messageId: msgId,
621
+ quoted
622
+ })
623
+ await relayMessage(jid, fullMsg.message, {
624
+ messageId: fullMsg.key.id
625
+ });
626
+
627
+ logger.debug(`Message successfully sent to ${jid}`);
628
+ if (delayMs && i < participantJids.length - 1) {
629
+ await new Promise(z => setTimeout(z, delayMs));
630
+ }
631
+ } catch (e) {
632
+ logger.error({ jid, e }, "Error sending message to");
936
633
  }
937
- return 'text';
634
+ }
635
+ return JSON.stringify({
636
+ members_total: participantJids.length,
637
+ message
638
+ }, null, 4);
938
639
  };
640
+
641
+ const getTypeMessage = (msg) => {
642
+ const message = Utils_1.normalizeMessageContent(msg)
643
+ if (message.reactionMessage) {
644
+ return 'reaction'
645
+ }
646
+ else if (getMediaType(message)) {
647
+ return 'media'
648
+ }
649
+ else {
650
+ return 'text'
651
+ }
652
+ }
653
+
939
654
  const getMediaType = (message) => {
940
655
  if (message.imageMessage) {
941
- return 'image';
656
+ return 'image'
942
657
  }
943
658
  else if (message.videoMessage) {
944
- return message.videoMessage.gifPlayback ? 'gif' : 'video';
659
+ return message.videoMessage.gifPlayback ? 'gif' : 'video'
945
660
  }
946
661
  else if (message.audioMessage) {
947
- return message.audioMessage.ptt ? 'ptt' : 'audio';
662
+ return message.audioMessage.ptt ? 'ptt' : 'audio'
948
663
  }
949
664
  else if (message.contactMessage) {
950
- return 'vcard';
665
+ return 'vcard'
951
666
  }
952
667
  else if (message.documentMessage) {
953
- return 'document';
668
+ return 'document'
954
669
  }
955
670
  else if (message.contactsArrayMessage) {
956
- return 'contact_array';
671
+ return 'contact_array'
957
672
  }
958
673
  else if (message.liveLocationMessage) {
959
- return 'livelocation';
674
+ return 'livelocation'
960
675
  }
961
676
  else if (message.stickerMessage) {
962
- return 'sticker';
677
+ return 'sticker'
963
678
  }
964
679
  else if (message.listMessage) {
965
- return 'list';
680
+ return 'list'
966
681
  }
967
682
  else if (message.listResponseMessage) {
968
- return 'list_response';
683
+ return 'list_response'
969
684
  }
970
685
  else if (message.buttonsResponseMessage) {
971
- return 'buttons_response';
686
+ return 'buttons_response'
972
687
  }
973
688
  else if (message.orderMessage) {
974
- return 'order';
689
+ return 'order'
975
690
  }
976
691
  else if (message.productMessage) {
977
- return 'product';
692
+ return 'product'
978
693
  }
979
694
  else if (message.interactiveResponseMessage) {
980
- return 'native_flow_response';
695
+ return 'native_flow_response'
981
696
  }
982
697
  else if (message.groupInviteMessage) {
983
- return 'url';
698
+ return 'url'
984
699
  }
985
- return '';
986
- };
700
+ else if (/https:\/\/wa\.me\/p\/\d+\/\d+/.test(message.extendedTextMessage?.text)) {
701
+ return 'productlink'
702
+ }
703
+ }
704
+
987
705
  const getButtonType = (message) => {
988
706
  if (message.listMessage) {
989
707
  return 'list'
@@ -1013,13 +731,13 @@ export const makeMessagesSocket = (config) => {
1013
731
  else if (message.interactiveMessage?.nativeFlowMessage) {
1014
732
  return 'native_flow'
1015
733
  }
1016
- };
1017
- const issuePrivacyTokens = async (jids, timestamp) => {
1018
- const t = (timestamp ?? unixTimestampSeconds()).toString();
734
+ }
735
+ const getPrivacyTokens = async (jids) => {
736
+ const t = Utils_1.unixTimestampSeconds().toString();
1019
737
  const result = await query({
1020
738
  tag: 'iq',
1021
739
  attrs: {
1022
- to: S_WHATSAPP_NET,
740
+ to: WABinary_1.S_WHATSAPP_NET,
1023
741
  type: 'set',
1024
742
  xmlns: 'privacy'
1025
743
  },
@@ -1030,7 +748,7 @@ export const makeMessagesSocket = (config) => {
1030
748
  content: jids.map(jid => ({
1031
749
  tag: 'token',
1032
750
  attrs: {
1033
- jid: jidNormalizedUser(jid),
751
+ jid: WABinary_1.jidNormalizedUser(jid),
1034
752
  t,
1035
753
  type: 'trusted_contact'
1036
754
  }
@@ -1039,47 +757,158 @@ export const makeMessagesSocket = (config) => {
1039
757
  ]
1040
758
  });
1041
759
  return result;
1042
- };
1043
- const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
1044
- const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
1045
- registerSocketEndHandler(() => {
1046
- if (!config.userDevicesCache && userDevicesCache.close) {
1047
- userDevicesCache.close();
760
+ }
761
+ const waUploadToServer = (0, Utils_1.getWAUploadToServer)(config, refreshMediaConn);
762
+ const luki = new imup(Utils_1, waUploadToServer, relayMessage, authState);
763
+ const waitForMsgMediaUpdate = (0, Utils_1.bindWaitForEvent)(ev, 'messages.media-update');
764
+ const sendMessage = async (jid, content, options = {}) => {
765
+ const userJid = authState.creds.me.id;
766
+ delete options.ephemeralExpiration
767
+ const { ptcp = false, quoted } = options;
768
+ const getParticipantAttr = () => ptcp ? { participant: { jid } } : {};
769
+ const messageType = luki.detectType(content);
770
+ if (typeof content === 'object' && 'disappearingMessagesInChat' in content &&
771
+ typeof content['disappearingMessagesInChat'] !== 'undefined' && WABinary_1.isJidGroup(jid)) {
772
+ const { disappearingMessagesInChat } = content
773
+
774
+ const value = typeof disappearingMessagesInChat === 'boolean' ?
775
+ (disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
776
+ disappearingMessagesInChat
777
+
778
+ await groupToggleEphemeral(jid, value)
779
+ }
780
+
781
+ else {
782
+ let mediaHandle
783
+
784
+
785
+ if (messageType) {
786
+ switch(messageType) {
787
+ case 'PAYMENT':
788
+ const paymentContent = await luki.handlePayment(content, quoted);
789
+ return await relayMessage(jid, paymentContent, {
790
+ messageId: Utils_1.generateMessageID(),
791
+ ...getParticipantAttr()
792
+ });
793
+
794
+ case 'PRODUCT':
795
+ const productContent = await luki.handleProduct(content, jid, quoted);
796
+ const productMsg = await Utils_1.generateWAMessageFromContent(jid, productContent, { quoted });
797
+ return await relayMessage(jid, productMsg.message, {
798
+ messageId: productMsg.key.id,
799
+ ...getParticipantAttr()
800
+ });
801
+
802
+ case 'INTERACTIVE':
803
+ const interactiveContent = await luki.handleInteractive(content, jid, quoted);
804
+ const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted });
805
+ return await relayMessage(jid, interactiveMsg.message, {
806
+ messageId: interactiveMsg.key.id,
807
+ ...getParticipantAttr()
808
+ });
809
+
810
+ case 'ALBUM':
811
+ return await luki.handleAlbum(content, jid, quoted)
812
+ case 'EVENT':
813
+ return await luki.handleEvent(content, jid, quoted)
814
+ case 'POLL_RESULT':
815
+ return await luki.handlePollResult(content, jid, quoted)
816
+ case 'ORDER':
817
+ return await luki.handleOrderMessage(content, jid, quoted)
818
+ case 'GROUP_STATUS':
819
+ return await luki.handleGroupStory(content, jid, quoted)
820
+ case 'GROUP_LABEL':
821
+ return await luki.handleGbLabel(content, jid)
822
+ }
1048
823
  }
1049
- mediaConn = undefined;
1050
- if (messageRetryManager) {
1051
- messageRetryManager.clear();
824
+ const fullMsg = await Utils_1.generateWAMessage(jid, content, {
825
+ logger,
826
+ userJid,
827
+ quoted,
828
+ getUrlInfo: text => link_preview_1.getUrlInfo(text, {
829
+ thumbnailWidth: linkPreviewImageThumbnailWidth,
830
+ fetchOpts: {
831
+ timeout: 3000,
832
+ ...axiosOptions || {}
833
+ },
834
+ logger,
835
+ uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
836
+ }),
837
+ upload: async (readStream, opts) => {
838
+ const up = await waUploadToServer(readStream, {
839
+ ...opts,
840
+ newsletter: WABinary_1.isJidNewsLetter(jid)
841
+ });
842
+ return up;
843
+ },
844
+ mediaCache: config.mediaCache,
845
+ options: config.options,
846
+ ...options
847
+ });
848
+
849
+ const isDeleteMsg = 'delete' in content && !!content.delete;
850
+ const isEditMsg = 'edit' in content && !!content.edit;
851
+ const isAiMsg = 'ai' in content && !!content.ai;
852
+
853
+ const additionalAttributes = {};
854
+ const additionalNodes = [];
855
+
856
+ if (isDeleteMsg) {
857
+ const fromMe = content.delete?.fromMe;
858
+ const isGroup = WABinary_1.isJidGroup(content.delete?.remoteJid);
859
+ additionalAttributes.edit = (isGroup && !fromMe) || WABinary_1.isJidNewsLetter(jid) ? '8' : '7';
860
+ } else if (isEditMsg) {
861
+ additionalAttributes.edit = WABinary_1.isJidNewsLetter(jid) ? '3' : '1';
862
+ } else if (isAiMsg) {
863
+ additionalNodes.push({
864
+ attrs: {
865
+ biz_bot: '1'
866
+ }, tag: "bot"
867
+ });
1052
868
  }
1053
- });
869
+
870
+ await relayMessage(jid, fullMsg.message, {
871
+ messageId: fullMsg.key.id,
872
+ cachedGroupMetadata: options.cachedGroupMetadata,
873
+ additionalNodes: isAiMsg ? additionalNodes : options.additionalNodes,
874
+ additionalAttributes,
875
+ statusJidList: options.statusJidList
876
+ });
877
+
878
+ if (config.emitOwnEvents) {
879
+ process.nextTick(() => {
880
+ processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
881
+ });
882
+ }
883
+ return fullMsg;
884
+ }
885
+ }
1054
886
  return {
1055
887
  ...sock,
1056
- userDevicesCache,
1057
- devicesMutex,
1058
- issuePrivacyTokens,
888
+ getPrivacyTokens,
1059
889
  assertSessions,
1060
890
  relayMessage,
891
+ sendMessageMembers,
1061
892
  sendReceipt,
1062
893
  sendReceipts,
894
+ luki,
895
+ sendMessage,
1063
896
  readMessages,
1064
897
  refreshMediaConn,
1065
- // Function (not getter) so the spread in chats.ts preserves the live closure binding.
1066
- getMediaHost: () => mediaHost,
898
+ getUSyncDevices,
899
+ createParticipantNodes,
1067
900
  waUploadToServer,
1068
- fetchPrivacySettings,
1069
901
  sendPeerDataOperationMessage,
1070
- createParticipantNodes,
1071
- getUSyncDevices,
1072
- messageRetryManager,
1073
- updateMemberLabel,
902
+ fetchPrivacySettings,
1074
903
  updateMediaMessage: async (message) => {
1075
- const content = assertMediaContent(message.message);
904
+ const content = (0, Utils_1.assertMediaContent)(message.message);
1076
905
  const mediaKey = content.mediaKey;
1077
906
  const meId = authState.creds.me.id;
1078
- const node = encryptMediaRetryRequest(message.key, mediaKey, meId);
907
+ const node = (0, Utils_1.encryptMediaRetryRequest)(message.key, mediaKey, meId);
1079
908
  let error = undefined;
1080
909
  await Promise.all([
1081
910
  sendNode(node),
1082
- waitForMsgMediaUpdate(async (update) => {
911
+ waitForMsgMediaUpdate(update => {
1083
912
  const result = update.find(c => c.key.id === message.key.id);
1084
913
  if (result) {
1085
914
  if (result.error) {
@@ -1087,16 +916,13 @@ export const makeMessagesSocket = (config) => {
1087
916
  }
1088
917
  else {
1089
918
  try {
1090
- const media = decryptMediaRetryData(result.media, mediaKey, result.key.id);
1091
- if (media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
1092
- const resultStr = proto.MediaRetryNotification.ResultType[media.result];
1093
- throw new Boom(`Media re-upload failed by device (${resultStr})`, {
1094
- data: media,
1095
- statusCode: getStatusCodeForMediaRetry(media.result) || 404
1096
- });
919
+ const media = (0, Utils_1.decryptMediaRetryData)(result.media, mediaKey, result.key.id);
920
+ if (media.result !== WAProto_1.proto.MediaRetryNotification.ResultType.SUCCESS) {
921
+ const resultStr = WAProto_1.proto.MediaRetryNotification.ResultType[media.result];
922
+ throw new boom_1.Boom(`Media re-upload failed by device (${resultStr})`, { data: media, statusCode: (0, Utils_1.getStatusCodeForMediaRetry)(media.result) || 404 });
1097
923
  }
1098
924
  content.directPath = media.directPath;
1099
- content.url = getUrlFromDirectPath(content.directPath, mediaHost);
925
+ content.url = (0, Utils_1.getUrlFromDirectPath)(content.directPath);
1100
926
  logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful');
1101
927
  }
1102
928
  catch (err) {
@@ -1110,182 +936,149 @@ export const makeMessagesSocket = (config) => {
1110
936
  if (error) {
1111
937
  throw error;
1112
938
  }
1113
- ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
939
+ ev.emit('messages.update', [
940
+ {
941
+ key: message.key,
942
+ update: {
943
+ message: message.message
944
+ }
945
+ }
946
+ ]);
1114
947
  return message;
1115
948
  },
1116
- sendMessage: async (jid, content, options = {}) => {
1117
- const userJid = authState.creds.me.id;
1118
- const luki = new imup(Utils_1, waUploadToServer, relayMessage)
1119
- const { quoted } = options;
1120
- const messageType = luki.detectType(content);
1121
- if (typeof content === 'object' &&
1122
- 'disappearingMessagesInChat' in content &&
1123
- typeof content['disappearingMessagesInChat'] !== 'undefined' &&
1124
- isJidGroup(jid)) {
1125
- const { disappearingMessagesInChat } = content;
1126
- const value = typeof disappearingMessagesInChat === 'boolean'
1127
- ? disappearingMessagesInChat
1128
- ? WA_DEFAULT_EPHEMERAL
1129
- : 0
1130
- : disappearingMessagesInChat;
1131
- await groupToggleEphemeral(jid, value);
949
+ sendText: async (jid, text, options, quoted = null) => {
950
+ return sendMessage(jid, {
951
+ text,
952
+ ...options
953
+ }, { quoted })
954
+ },
955
+ sendImage: async (jid, image, caption, options, quoted = null) => {
956
+ return sendMessage(jid, {
957
+ image,
958
+ caption,
959
+ ...options
960
+ }, { quoted })
961
+ },
962
+ sendVideo: async (jid, video, caption, options, quoted = null) => {
963
+ return sendMessage(jid, {
964
+ video,
965
+ caption,
966
+ ...options
967
+ }, { quoted })
968
+ },
969
+ sendDocument: async (jid, document, caption, options, quoted = null) => {
970
+ return sendMessage(jid, {
971
+ document,
972
+ caption,
973
+ ...options
974
+ }, { quoted })
975
+ },
976
+ sendAudio: async (jid, audio, options, quoted = null) => {
977
+ return sendMessage(jid, {
978
+ audio,
979
+ ...options
980
+ }, { quoted })
981
+ },
982
+ sendLocation: async (jid, name, degreesLongitude, degreesLatitude, url, address, options, quoted = null) => {
983
+ return sendMessage(jid, {
984
+ location: {
985
+ degreesLongitude,
986
+ degreesLatitude,
987
+ name,
988
+ url,
989
+ address
990
+ },
991
+ ...options
992
+ }, { quoted })
993
+ },
994
+ sendPoll: async (jid, name, pollVote = [], multiSelect = false, options, quoted = null) => {
995
+ const selectableCount = multiSelect ? pollVote.length : 1;
996
+
997
+ return sendMessage(jid, {
998
+ poll: {
999
+ name,
1000
+ values: pollVote,
1001
+ selectableCount
1002
+ },
1003
+ ...options
1004
+ }, { quoted });
1005
+ },
1006
+ sendQuiz: (
1007
+ jid,
1008
+ name,
1009
+ pollVote = [],
1010
+ answer,
1011
+ options,
1012
+ quoted
1013
+ ) => {
1014
+ const poll = {
1015
+ name,
1016
+ values: pollVote,
1017
+ selectableCount: 1,
1018
+ type: "QUIZ",
1019
+ answer: { optionName: answer }
1132
1020
  }
1133
- else {
1134
- if (messageType) {
1135
- switch(messageType) {
1136
- case 'PAYMENT':
1137
- const paymentContent = await luki.handlePayment(content, quoted);
1138
- return await relayMessage(jid, paymentContent, {
1139
- messageId: Utils_1.generateMessageID()
1140
- });
1141
- case 'PRODUCT':
1142
- const productContent = await luki.handleProduct(content, jid, quoted);
1143
- const productMsg = await Utils_1.generateWAMessageFromContent(jid, productContent, { quoted });
1144
- return await relayMessage(jid, productMsg.message, {
1145
- messageId: productMsg.key.id,
1146
- });
1147
-
1148
- case 'INTERACTIVE':
1149
- const interactiveContent = await luki.handleInteractive(content, jid, quoted);
1150
- const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted });
1151
- return await relayMessage(jid, interactiveMsg.message, {
1152
- messageId: interactiveMsg.key.id
1153
- });
1154
- case 'ALBUM':
1155
- return await luki.handleAlbum(content, jid, quoted)
1156
- case 'EVENT':
1157
- return await luki.handleEvent(content, jid, quoted)
1158
- case 'POLL_RESULT':
1159
- return await luki.handlePollResult(content, jid, quoted)
1160
- case 'ORDER':
1161
- return await luki.handleOrderMessage(content, jid, quoted)
1162
- case 'GROUP_STATUS':
1163
- return await luki.handleGroupStory(content, jid, quoted)
1164
- case 'GROUP_LABEL':
1165
- return await luki.handleGbLabel(content, jid)
1166
- }
1167
- }
1168
- const fullMsg = await generateWAMessage(jid, content, {
1169
- logger,
1170
- userJid,
1171
- getUrlInfo: text => getUrlInfo(text, {
1172
- thumbnailWidth: linkPreviewImageThumbnailWidth,
1173
- fetchOpts: {
1174
- timeout: 3000,
1175
- ...(httpRequestOptions || {})
1176
- },
1177
- logger,
1178
- uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
1179
- }),
1180
- //TODO: CACHE
1181
- getProfilePicUrl: sock.profilePictureUrl,
1182
- getCallLink: sock.createCallLink,
1183
- upload: waUploadToServer,
1184
- mediaCache: config.mediaCache,
1185
- options: config.options,
1186
- messageId: generateMessageIDV2(sock.user?.id),
1187
- ...options
1188
- });
1189
- const isEventMsg = 'event' in content && !!content.event;
1190
- const isDeleteMsg = 'delete' in content && !!content.delete;
1191
- const isEditMsg = 'edit' in content && !!content.edit;
1192
- const isPinMsg = 'pin' in content && !!content.pin;
1193
- const isPollMessage = 'poll' in content && !!content.poll;
1194
- const additionalAttributes = {};
1195
- const additionalNodes = [];
1196
- // required for delete
1197
- if (isDeleteMsg) {
1198
- // if the chat is a group, and I am not the author, then delete the message as an admin
1199
- if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
1200
- additionalAttributes.edit = '8';
1201
- }
1202
- else {
1203
- additionalAttributes.edit = '7';
1021
+ return sendMessage(jid, {
1022
+ poll,
1023
+ ...options
1024
+ }, { quoted })
1025
+ },
1026
+ sendPtv: (jid, ptv, options, quoted = null) => {
1027
+ return sendMessage(jid, {
1028
+ ptv,
1029
+ ...options
1030
+ }, { quoted })
1031
+ },
1032
+ statusMention: async (jid, content) => {
1033
+ const msg = Utils_1.generateWAMessageFromContent("status@broadcast", content, {})
1034
+
1035
+ await relayMessage("status@broadcast", msg.message, {
1036
+ messageId: msg.key.id,
1037
+ statusJidList: [jid, authState.creds.me.id],
1038
+ additionalNodes: [
1039
+ {
1040
+ tag: "meta",
1041
+ attrs: {},
1042
+ content: [
1043
+ {
1044
+ tag: "mentioned_users",
1045
+ attrs: {},
1046
+ content: [
1047
+ {
1048
+ tag: "to",
1049
+ attrs: { jid },
1050
+ content: undefined
1051
+ }
1052
+ ]
1053
+ }
1054
+ ]
1204
1055
  }
1205
- }
1206
- else if (isEditMsg) {
1207
- additionalAttributes.edit = '1';
1208
- }
1209
- else if (isPinMsg) {
1210
- additionalAttributes.edit = '2';
1211
- }
1212
- else if (isPollMessage) {
1213
- additionalNodes.push({
1214
- tag: 'meta',
1215
- attrs: {
1216
- polltype: 'creation'
1217
- }
1218
- });
1219
- }
1220
- else if (isEventMsg) {
1221
- additionalNodes.push({
1222
- tag: 'meta',
1223
- attrs: {
1224
- event_type: 'creation'
1056
+ ]
1057
+ })
1058
+
1059
+ const mentionMsg = {
1060
+ statusMentionMessage: {
1061
+ message: {
1062
+ protocolMessage: {
1063
+ key: msg.key,
1064
+ type: "STATUS_MENTION_MESSAGE",
1065
+ timestamp: Math.floor(Date.now() / 1000)
1225
1066
  }
1226
- });
1227
- }
1228
- await relayMessage(jid, fullMsg.message, {
1229
- messageId: fullMsg.key.id,
1230
- useCachedGroupMetadata: options.useCachedGroupMetadata,
1231
- additionalAttributes,
1232
- statusJidList: options.statusJidList,
1233
- additionalNodes: aiLabel ? additionalNodes : options.additionalNodes
1234
- });
1235
- if (config.emitOwnEvents) {
1236
- process.nextTick(async () => {
1237
- await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1238
- });
1239
- }
1240
- return fullMsg;
1241
- }
1242
- },
1243
- sendMessageMembers: async (jid, message, options = {}) => {
1244
- const {
1245
- messageId: idm,
1246
- quoted,
1247
- delayMs = 1500,
1248
- useUserDevicesCache = true,
1249
- cachedGroupMetadata,
1250
- onlyMember = true
1251
- } = options;
1252
- const { server } = jidDecode(jid);
1253
- if (server !== "g.us") throw new Error("@g.us server required");
1254
- const meId = authState.creds.me.id;
1255
- const messages = Utils_1.normalizeMessageContent(message);
1256
- const groupData = cachedGroupMetadata? await cachedGroupMetadata(jid) : await groupMetadata(jid);
1257
- const isLid = groupData.addressingMode === "lid";
1258
- const isAdmin = groupData.participants.filter((x) => x.admin !== null).map((y) => y.id)
1259
- let participantJids = groupData.participants.map(z => z.id);
1260
- if (onlyMember) {
1261
- participantJids = isAdmin ? isAdmin : participantJids;
1262
- }
1263
- logger.info(`Sending message to ${participantJids.length} members from ${jid}`);
1264
- for (let i = 0; i < participantJids.length; i++) {
1265
- const jid = participantJids[i];
1266
- if (areJidsSameUser(jid, meId)) continue;
1267
- try {
1268
- const msgId = `${idm || Utils_1.generateMessageID()}_${i}`;
1269
- const fullMsg = await Utils_1.generateWAMessageFromContent(jid, message, {
1270
- messageId: msgId,
1271
- quoted
1272
- })
1273
- await relayMessage(jid, fullMsg.message, {
1274
- messageId: fullMsg.key.id
1275
- });
1276
- logger.debug(`Message successfully sent to ${jid}`);
1277
- if (delayMs && i < participantJids.length - 1) {
1278
- await new Promise(z => setTimeout(z, delayMs));
1279
1067
  }
1280
- } catch (e) {
1281
- logger.error({ jid, e }, "Error sending message to");
1282
1068
  }
1283
1069
  }
1284
- return JSON.stringify({
1285
- members_total: participantJids.length,
1286
- message
1287
- }, null, 4);
1070
+
1071
+ const x = Utils_1.generateWAMessageFromContent(jid, mentionMsg, {})
1072
+ return relayMessage(jid, x.message, {
1073
+ messageId: x.key.id,
1074
+ additionalNodes: [
1075
+ {
1076
+ tag: "meta",
1077
+ attrs: { is_status_mention: "true" }
1078
+ }
1079
+ ]
1080
+ })
1288
1081
  }
1289
- };
1082
+ }
1290
1083
  };
1291
- //# sourceMappingURL=messages-send.js.map
1084
+ exports.makeMessagesSocket = makeMessagesSocket;