@d0v3riz/baileys 6.7.25 → 7.0.0-rc.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 (208) hide show
  1. package/README.md +23 -8
  2. package/WAProto/GenerateStatics.sh +2 -2
  3. package/WAProto/WAProto.proto +1339 -493
  4. package/WAProto/fix-imports.js +1 -1
  5. package/WAProto/index.d.ts +4585 -44041
  6. package/WAProto/index.js +80831 -148208
  7. package/lib/Defaults/index.d.ts +13 -3
  8. package/lib/Defaults/index.d.ts.map +1 -1
  9. package/lib/Defaults/index.js +27 -13
  10. package/lib/Defaults/index.js.map +1 -1
  11. package/lib/Signal/Group/group_cipher.d.ts +1 -2
  12. package/lib/Signal/Group/group_cipher.d.ts.map +1 -1
  13. package/lib/Signal/Group/group_cipher.js +29 -41
  14. package/lib/Signal/Group/group_cipher.js.map +1 -1
  15. package/lib/Signal/Group/keyhelper.d.ts.map +1 -1
  16. package/lib/Signal/Group/keyhelper.js +0 -1
  17. package/lib/Signal/Group/keyhelper.js.map +1 -1
  18. package/lib/Signal/Group/sender-chain-key.d.ts +1 -1
  19. package/lib/Signal/Group/sender-chain-key.d.ts.map +1 -1
  20. package/lib/Signal/Group/sender-chain-key.js +1 -7
  21. package/lib/Signal/Group/sender-chain-key.js.map +1 -1
  22. package/lib/Signal/Group/sender-key-distribution-message.js +2 -2
  23. package/lib/Signal/Group/sender-key-distribution-message.js.map +1 -1
  24. package/lib/Signal/Group/sender-key-message.d.ts.map +1 -1
  25. package/lib/Signal/Group/sender-key-message.js +0 -1
  26. package/lib/Signal/Group/sender-key-message.js.map +1 -1
  27. package/lib/Signal/Group/sender-key-record.d.ts +1 -1
  28. package/lib/Signal/Group/sender-key-record.d.ts.map +1 -1
  29. package/lib/Signal/Group/sender-key-record.js +2 -11
  30. package/lib/Signal/Group/sender-key-record.js.map +1 -1
  31. package/lib/Signal/Group/sender-key-state.d.ts +4 -4
  32. package/lib/Signal/Group/sender-key-state.d.ts.map +1 -1
  33. package/lib/Signal/Group/sender-key-state.js +21 -33
  34. package/lib/Signal/Group/sender-key-state.js.map +1 -1
  35. package/lib/Signal/Group/sender-message-key.d.ts.map +1 -1
  36. package/lib/Signal/Group/sender-message-key.js +0 -1
  37. package/lib/Signal/Group/sender-message-key.js.map +1 -1
  38. package/lib/Signal/libsignal.d.ts +4 -3
  39. package/lib/Signal/libsignal.d.ts.map +1 -1
  40. package/lib/Signal/libsignal.js +243 -42
  41. package/lib/Signal/libsignal.js.map +1 -1
  42. package/lib/Signal/lid-mapping.d.ts +23 -0
  43. package/lib/Signal/lid-mapping.d.ts.map +1 -0
  44. package/lib/Signal/lid-mapping.js +171 -0
  45. package/lib/Signal/lid-mapping.js.map +1 -0
  46. package/lib/Socket/business.d.ts +29 -17
  47. package/lib/Socket/business.d.ts.map +1 -1
  48. package/lib/Socket/business.js +122 -1
  49. package/lib/Socket/business.js.map +1 -1
  50. package/lib/Socket/chats.d.ts +15 -9
  51. package/lib/Socket/chats.d.ts.map +1 -1
  52. package/lib/Socket/chats.js +49 -20
  53. package/lib/Socket/chats.js.map +1 -1
  54. package/lib/Socket/communities.d.ts +39 -14
  55. package/lib/Socket/communities.d.ts.map +1 -1
  56. package/lib/Socket/communities.js +82 -2
  57. package/lib/Socket/communities.js.map +1 -1
  58. package/lib/Socket/groups.d.ts +14 -9
  59. package/lib/Socket/groups.d.ts.map +1 -1
  60. package/lib/Socket/groups.js +14 -11
  61. package/lib/Socket/groups.js.map +1 -1
  62. package/lib/Socket/index.d.ts +39 -14
  63. package/lib/Socket/index.d.ts.map +1 -1
  64. package/lib/Socket/index.js +1 -0
  65. package/lib/Socket/index.js.map +1 -1
  66. package/lib/Socket/messages-recv.d.ts +24 -16
  67. package/lib/Socket/messages-recv.d.ts.map +1 -1
  68. package/lib/Socket/messages-recv.js +463 -319
  69. package/lib/Socket/messages-recv.js.map +1 -1
  70. package/lib/Socket/messages-send.d.ts +25 -16
  71. package/lib/Socket/messages-send.d.ts.map +1 -1
  72. package/lib/Socket/messages-send.js +364 -124
  73. package/lib/Socket/messages-send.js.map +1 -1
  74. package/lib/Socket/newsletter.d.ts +16 -12
  75. package/lib/Socket/newsletter.d.ts.map +1 -1
  76. package/lib/Socket/newsletter.js +3 -1
  77. package/lib/Socket/newsletter.js.map +1 -1
  78. package/lib/Socket/socket.d.ts +11 -3
  79. package/lib/Socket/socket.d.ts.map +1 -1
  80. package/lib/Socket/socket.js +305 -71
  81. package/lib/Socket/socket.js.map +1 -1
  82. package/lib/Types/Auth.d.ts +8 -1
  83. package/lib/Types/Auth.d.ts.map +1 -1
  84. package/lib/Types/Bussines.d.ts +25 -0
  85. package/lib/Types/Bussines.d.ts.map +1 -0
  86. package/lib/Types/Bussines.js +2 -0
  87. package/lib/Types/Bussines.js.map +1 -0
  88. package/lib/Types/Chat.d.ts +5 -0
  89. package/lib/Types/Chat.d.ts.map +1 -1
  90. package/lib/Types/Chat.js.map +1 -1
  91. package/lib/Types/Contact.d.ts +4 -4
  92. package/lib/Types/Contact.d.ts.map +1 -1
  93. package/lib/Types/Events.d.ts +8 -5
  94. package/lib/Types/Events.d.ts.map +1 -1
  95. package/lib/Types/GroupMetadata.d.ts +7 -4
  96. package/lib/Types/GroupMetadata.d.ts.map +1 -1
  97. package/lib/Types/Message.d.ts +36 -12
  98. package/lib/Types/Message.d.ts.map +1 -1
  99. package/lib/Types/Message.js +5 -1
  100. package/lib/Types/Message.js.map +1 -1
  101. package/lib/Types/Signal.d.ts +18 -0
  102. package/lib/Types/Signal.d.ts.map +1 -1
  103. package/lib/Types/Socket.d.ts +24 -13
  104. package/lib/Types/Socket.d.ts.map +1 -1
  105. package/lib/Types/Socket.js.map +1 -1
  106. package/lib/Utils/auth-utils.d.ts +2 -2
  107. package/lib/Utils/auth-utils.d.ts.map +1 -1
  108. package/lib/Utils/auth-utils.js +178 -111
  109. package/lib/Utils/auth-utils.js.map +1 -1
  110. package/lib/Utils/browser-utils.d.ts +4 -0
  111. package/lib/Utils/browser-utils.d.ts.map +1 -0
  112. package/lib/Utils/browser-utils.js +28 -0
  113. package/lib/Utils/browser-utils.js.map +1 -0
  114. package/lib/Utils/chat-utils.d.ts +6 -7
  115. package/lib/Utils/chat-utils.d.ts.map +1 -1
  116. package/lib/Utils/chat-utils.js +19 -2
  117. package/lib/Utils/chat-utils.js.map +1 -1
  118. package/lib/Utils/crypto.d.ts +6 -6
  119. package/lib/Utils/crypto.d.ts.map +1 -1
  120. package/lib/Utils/crypto.js +16 -12
  121. package/lib/Utils/crypto.js.map +1 -1
  122. package/lib/Utils/decode-wa-message.d.ts +14 -2
  123. package/lib/Utils/decode-wa-message.d.ts.map +1 -1
  124. package/lib/Utils/decode-wa-message.js +99 -14
  125. package/lib/Utils/decode-wa-message.js.map +1 -1
  126. package/lib/Utils/event-buffer.d.ts +0 -1
  127. package/lib/Utils/event-buffer.d.ts.map +1 -1
  128. package/lib/Utils/event-buffer.js +63 -18
  129. package/lib/Utils/event-buffer.js.map +1 -1
  130. package/lib/Utils/generics.d.ts +5 -7
  131. package/lib/Utils/generics.d.ts.map +1 -1
  132. package/lib/Utils/generics.js +58 -50
  133. package/lib/Utils/generics.js.map +1 -1
  134. package/lib/Utils/history.d.ts +8 -9
  135. package/lib/Utils/history.d.ts.map +1 -1
  136. package/lib/Utils/history.js +8 -3
  137. package/lib/Utils/history.js.map +1 -1
  138. package/lib/Utils/index.d.ts +2 -0
  139. package/lib/Utils/index.d.ts.map +1 -1
  140. package/lib/Utils/index.js +2 -0
  141. package/lib/Utils/index.js.map +1 -1
  142. package/lib/Utils/link-preview.d.ts +1 -2
  143. package/lib/Utils/link-preview.d.ts.map +1 -1
  144. package/lib/Utils/link-preview.js +1 -1
  145. package/lib/Utils/link-preview.js.map +1 -1
  146. package/lib/Utils/message-retry-manager.d.ts +82 -0
  147. package/lib/Utils/message-retry-manager.d.ts.map +1 -0
  148. package/lib/Utils/message-retry-manager.js +149 -0
  149. package/lib/Utils/message-retry-manager.js.map +1 -0
  150. package/lib/Utils/messages-media.d.ts +14 -12
  151. package/lib/Utils/messages-media.d.ts.map +1 -1
  152. package/lib/Utils/messages-media.js +47 -23
  153. package/lib/Utils/messages-media.js.map +1 -1
  154. package/lib/Utils/messages.d.ts +4 -4
  155. package/lib/Utils/messages.d.ts.map +1 -1
  156. package/lib/Utils/messages.js +55 -21
  157. package/lib/Utils/messages.js.map +1 -1
  158. package/lib/Utils/noise-handler.js +2 -1
  159. package/lib/Utils/noise-handler.js.map +1 -1
  160. package/lib/Utils/pre-key-manager.d.ts +28 -0
  161. package/lib/Utils/pre-key-manager.d.ts.map +1 -0
  162. package/lib/Utils/pre-key-manager.js +106 -0
  163. package/lib/Utils/pre-key-manager.js.map +1 -0
  164. package/lib/Utils/process-message.d.ts +8 -8
  165. package/lib/Utils/process-message.d.ts.map +1 -1
  166. package/lib/Utils/process-message.js +68 -23
  167. package/lib/Utils/process-message.js.map +1 -1
  168. package/lib/Utils/signal.d.ts +4 -4
  169. package/lib/Utils/signal.d.ts.map +1 -1
  170. package/lib/Utils/signal.js +21 -12
  171. package/lib/Utils/signal.js.map +1 -1
  172. package/lib/Utils/validate-connection.d.ts.map +1 -1
  173. package/lib/Utils/validate-connection.js +50 -14
  174. package/lib/Utils/validate-connection.js.map +1 -1
  175. package/lib/WABinary/decode.d.ts.map +1 -1
  176. package/lib/WABinary/decode.js +12 -2
  177. package/lib/WABinary/decode.js.map +1 -1
  178. package/lib/WABinary/generic-utils.js +1 -1
  179. package/lib/WABinary/generic-utils.js.map +1 -1
  180. package/lib/WABinary/jid-utils.d.ts +18 -6
  181. package/lib/WABinary/jid-utils.d.ts.map +1 -1
  182. package/lib/WABinary/jid-utils.js +52 -8
  183. package/lib/WABinary/jid-utils.js.map +1 -1
  184. package/lib/WAM/constants.d.ts +1 -1
  185. package/lib/WAM/constants.d.ts.map +1 -1
  186. package/lib/WAM/constants.js +18516 -10904
  187. package/lib/WAM/constants.js.map +1 -1
  188. package/lib/WAM/encode.d.ts.map +1 -1
  189. package/lib/WAM/encode.js +0 -1
  190. package/lib/WAM/encode.js.map +1 -1
  191. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +2 -1
  192. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +1 -1
  193. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +10 -2
  194. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +1 -1
  195. package/lib/WAUSync/USyncQuery.d.ts +1 -1
  196. package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
  197. package/lib/WAUSync/USyncQuery.js +23 -20
  198. package/lib/WAUSync/USyncQuery.js.map +1 -1
  199. package/package.json +16 -11
  200. package/lib/Defaults/baileys-version.json +0 -3
  201. package/lib/Signal/Group/queue-job.d.ts +0 -2
  202. package/lib/Signal/Group/queue-job.d.ts.map +0 -1
  203. package/lib/Signal/Group/queue-job.js +0 -54
  204. package/lib/Signal/Group/queue-job.js.map +0 -1
  205. package/lib/Socket/usync.d.ts +0 -37
  206. package/lib/Socket/usync.d.ts.map +0 -1
  207. package/lib/Socket/usync.js +0 -63
  208. package/lib/Socket/usync.js.map +0 -1
@@ -2,21 +2,29 @@ import NodeCache from '@cacheable/node-cache';
2
2
  import { Boom } from '@hapi/boom';
3
3
  import { proto } from '../../WAProto/index.js';
4
4
  import { DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
5
- import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/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';
6
6
  import { getUrlInfo } from '../Utils/link-preview.js';
7
- import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, isJidUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
7
+ import { makeKeyedMutex } from '../Utils/make-mutex.js';
8
+ import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidGroup, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
8
9
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
9
- import { makeGroupsSocket } from './groups.js';
10
10
  import { makeNewsletterSocket } from './newsletter.js';
11
11
  export const makeMessagesSocket = (config) => {
12
- const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: axiosOptions, patchMessageBeforeSending, cachedGroupMetadata } = config;
13
- const sock = makeNewsletterSocket(makeGroupsSocket(config));
12
+ const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
13
+ const sock = makeNewsletterSocket(config);
14
14
  const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral } = sock;
15
15
  const userDevicesCache = config.userDevicesCache ||
16
16
  new NodeCache({
17
17
  stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
18
18
  useClones: false
19
19
  });
20
+ const peerSessionsCache = new NodeCache({
21
+ stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES,
22
+ useClones: false
23
+ });
24
+ // Initialize message retry manager if enabled
25
+ const messageRetryManager = enableRecentMessageCache ? new MessageRetryManager(logger, maxMsgRetryCount) : null;
26
+ // Prevent race conditions in Signal session encryption by user
27
+ const encryptionMutex = makeKeyedMutex();
20
28
  let mediaConn;
21
29
  const refreshMediaConn = async (forceGet = false) => {
22
30
  const media = await mediaConn;
@@ -32,6 +40,7 @@ export const makeMessagesSocket = (config) => {
32
40
  content: [{ tag: 'media_conn', attrs: {} }]
33
41
  });
34
42
  const mediaConnNode = getBinaryNodeChild(result, 'media_conn');
43
+ // TODO: explore full length of data that whatsapp provides
35
44
  const node = {
36
45
  hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
37
46
  hostname: attrs.hostname,
@@ -65,7 +74,7 @@ export const makeMessagesSocket = (config) => {
65
74
  if (isReadReceipt) {
66
75
  node.attrs.t = unixTimestampSeconds().toString();
67
76
  }
68
- if (type === 'sender' && isJidUser(jid)) {
77
+ if (type === 'sender' && (isPnUser(jid) || isLidUser(jid))) {
69
78
  node.attrs.recipient = jid;
70
79
  node.attrs.to = participant;
71
80
  }
@@ -115,14 +124,39 @@ export const makeMessagesSocket = (config) => {
115
124
  logger.debug('not using cache for devices');
116
125
  }
117
126
  const toFetch = [];
118
- jids = Array.from(new Set(jids));
119
- for (let jid of jids) {
120
- const user = jidDecode(jid)?.user;
127
+ const jidsWithUser = jids
128
+ .map(jid => {
129
+ const decoded = jidDecode(jid);
130
+ const user = decoded?.user;
131
+ const device = decoded?.device;
132
+ const isExplicitDevice = typeof device === 'number' && device >= 0;
133
+ if (isExplicitDevice && user) {
134
+ deviceResults.push({
135
+ user,
136
+ device,
137
+ jid
138
+ });
139
+ return null;
140
+ }
121
141
  jid = jidNormalizedUser(jid);
142
+ return { jid, user };
143
+ })
144
+ .filter(jid => jid !== null);
145
+ let mgetDevices;
146
+ if (useCache && userDevicesCache.mget) {
147
+ const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean);
148
+ mgetDevices = await userDevicesCache.mget(usersToFetch);
149
+ }
150
+ for (const { jid, user } of jidsWithUser) {
122
151
  if (useCache) {
123
- const devices = userDevicesCache.get(user);
152
+ const devices = mgetDevices?.[user] ||
153
+ (userDevicesCache.mget ? undefined : (await userDevicesCache.get(user)));
124
154
  if (devices) {
125
- deviceResults.push(...devices);
155
+ const devicesWithJid = devices.map(d => ({
156
+ ...d,
157
+ jid: jidEncode(d.user, d.server, d.device)
158
+ }));
159
+ deviceResults.push(...devicesWithJid);
126
160
  logger.trace({ user }, 'using cache for devices');
127
161
  }
128
162
  else {
@@ -136,43 +170,111 @@ export const makeMessagesSocket = (config) => {
136
170
  if (!toFetch.length) {
137
171
  return deviceResults;
138
172
  }
139
- const query = new USyncQuery().withContext('message').withDeviceProtocol();
173
+ const requestedLidUsers = new Set();
174
+ for (const jid of toFetch) {
175
+ if (isLidUser(jid) || isHostedLidUser(jid)) {
176
+ const user = jidDecode(jid)?.user;
177
+ if (user)
178
+ requestedLidUsers.add(user);
179
+ }
180
+ }
181
+ const query = new USyncQuery().withContext('message').withDeviceProtocol().withLIDProtocol();
140
182
  for (const jid of toFetch) {
141
- query.withUser(new USyncUser().withId(jid));
183
+ 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
142
184
  }
143
185
  const result = await sock.executeUSyncQuery(query);
144
186
  if (result) {
145
- const extracted = extractDeviceJids(result?.list, authState.creds.me.id, ignoreZeroDevices);
187
+ // TODO: LID MAP this stuff (lid protocol will now return lid with devices)
188
+ const lidResults = result.list.filter(a => !!a.lid);
189
+ if (lidResults.length > 0) {
190
+ logger.trace('Storing LID maps from device call');
191
+ await signalRepository.lidMapping.storeLIDPNMappings(lidResults.map(a => ({ lid: a.lid, pn: a.id })));
192
+ }
193
+ const extracted = extractDeviceJids(result?.list, authState.creds.me.id, authState.creds.me.lid, ignoreZeroDevices);
146
194
  const deviceMap = {};
147
195
  for (const item of extracted) {
148
196
  deviceMap[item.user] = deviceMap[item.user] || [];
149
197
  deviceMap[item.user]?.push(item);
150
- deviceResults.push(item);
151
198
  }
152
- for (const key in deviceMap) {
153
- userDevicesCache.set(key, deviceMap[key]);
199
+ // Process each user's devices as a group for bulk LID migration
200
+ for (const [user, userDevices] of Object.entries(deviceMap)) {
201
+ const isLidUser = requestedLidUsers.has(user);
202
+ // Process all devices for this user
203
+ for (const item of userDevices) {
204
+ const finalJid = isLidUser
205
+ ? jidEncode(user, item.server, item.device)
206
+ : jidEncode(item.user, item.server, item.device);
207
+ deviceResults.push({
208
+ ...item,
209
+ jid: finalJid
210
+ });
211
+ logger.debug({
212
+ user: item.user,
213
+ device: item.device,
214
+ finalJid,
215
+ usedLid: isLidUser
216
+ }, 'Processed device with LID priority');
217
+ }
218
+ }
219
+ if (userDevicesCache.mset) {
220
+ // if the cache supports mset, we can set all devices in one go
221
+ await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })));
222
+ }
223
+ else {
224
+ for (const key in deviceMap) {
225
+ if (deviceMap[key])
226
+ await userDevicesCache.set(key, deviceMap[key]);
227
+ }
228
+ }
229
+ const userDeviceUpdates = {};
230
+ for (const [userId, devices] of Object.entries(deviceMap)) {
231
+ if (devices && devices.length > 0) {
232
+ userDeviceUpdates[userId] = devices.map(d => d.device?.toString() || '0');
233
+ }
234
+ }
235
+ if (Object.keys(userDeviceUpdates).length > 0) {
236
+ try {
237
+ await authState.keys.set({ 'device-list': userDeviceUpdates });
238
+ logger.debug({ userCount: Object.keys(userDeviceUpdates).length }, 'stored user device lists for bulk migration');
239
+ }
240
+ catch (error) {
241
+ logger.warn({ error }, 'failed to store user device lists');
242
+ }
154
243
  }
155
244
  }
156
245
  return deviceResults;
157
246
  };
158
- const assertSessions = async (jids, force) => {
247
+ const assertSessions = async (jids) => {
159
248
  let didFetchNewSession = false;
160
- let jidsRequiringFetch = [];
161
- if (force) {
162
- jidsRequiringFetch = jids;
163
- }
164
- else {
165
- const addrs = jids.map(jid => signalRepository.jidToSignalProtocolAddress(jid));
166
- const sessions = await authState.keys.get('session', addrs);
167
- for (const jid of jids) {
168
- const signalId = signalRepository.jidToSignalProtocolAddress(jid);
169
- if (!sessions[signalId]) {
170
- jidsRequiringFetch.push(jid);
249
+ const uniqueJids = [...new Set(jids)]; // Deduplicate JIDs
250
+ const jidsRequiringFetch = [];
251
+ logger.debug({ jids }, 'assertSessions call with jids');
252
+ // Check peerSessionsCache and validate sessions using libsignal loadSession
253
+ for (const jid of uniqueJids) {
254
+ const signalId = signalRepository.jidToSignalProtocolAddress(jid);
255
+ const cachedSession = peerSessionsCache.get(signalId);
256
+ if (cachedSession !== undefined) {
257
+ if (cachedSession) {
258
+ continue; // Session exists in cache
171
259
  }
172
260
  }
261
+ else {
262
+ const sessionValidation = await signalRepository.validateSession(jid);
263
+ const hasSession = sessionValidation.exists;
264
+ peerSessionsCache.set(signalId, hasSession);
265
+ if (hasSession) {
266
+ continue;
267
+ }
268
+ }
269
+ jidsRequiringFetch.push(jid);
173
270
  }
174
271
  if (jidsRequiringFetch.length) {
175
- logger.debug({ jidsRequiringFetch }, 'fetching sessions');
272
+ // LID if mapped, otherwise original
273
+ const wireJids = [
274
+ ...jidsRequiringFetch.filter(jid => !!isLidUser(jid) || !!isHostedLidUser(jid)),
275
+ ...((await signalRepository.lidMapping.getLIDsForPNs(jidsRequiringFetch.filter(jid => !!isPnUser(jid) || !!isHostedPnUser(jid)))) || []).map(a => a.lid)
276
+ ];
277
+ logger.debug({ jidsRequiringFetch, wireJids }, 'fetching sessions');
176
278
  const result = await query({
177
279
  tag: 'iq',
178
280
  attrs: {
@@ -184,7 +286,7 @@ export const makeMessagesSocket = (config) => {
184
286
  {
185
287
  tag: 'key',
186
288
  attrs: {},
187
- content: jidsRequiringFetch.map(jid => ({
289
+ content: wireJids.map(jid => ({
188
290
  tag: 'user',
189
291
  attrs: { jid }
190
292
  }))
@@ -193,6 +295,11 @@ export const makeMessagesSocket = (config) => {
193
295
  });
194
296
  await parseAndInjectE2ESessions(result, signalRepository);
195
297
  didFetchNewSession = true;
298
+ // Cache fetched sessions using wire JIDs
299
+ for (const wireJid of wireJids) {
300
+ const signalId = signalRepository.jidToSignalProtocolAddress(wireJid);
301
+ peerSessionsCache.set(signalId, true);
302
+ }
196
303
  }
197
304
  return didFetchNewSession;
198
305
  };
@@ -212,59 +319,91 @@ export const makeMessagesSocket = (config) => {
212
319
  additionalAttributes: {
213
320
  category: 'peer',
214
321
  push_priority: 'high_force'
215
- }
322
+ },
323
+ additionalNodes: [
324
+ {
325
+ tag: 'meta',
326
+ attrs: { appdata: 'default' }
327
+ }
328
+ ]
216
329
  });
217
330
  return msgId;
218
331
  };
219
- const createParticipantNodes = async (jids, message, extraAttrs) => {
220
- let patched = await patchMessageBeforeSending(message, jids);
221
- if (!Array.isArray(patched)) {
222
- patched = jids ? jids.map(jid => ({ recipientJid: jid, ...patched })) : [patched];
223
- }
332
+ const createParticipantNodes = async (recipientJids, message, extraAttrs, dsmMessage) => {
333
+ if (!recipientJids.length) {
334
+ return { nodes: [], shouldIncludeDeviceIdentity: false };
335
+ }
336
+ const patched = await patchMessageBeforeSending(message, recipientJids);
337
+ const patchedMessages = Array.isArray(patched)
338
+ ? patched
339
+ : recipientJids.map(jid => ({ recipientJid: jid, message: patched }));
224
340
  let shouldIncludeDeviceIdentity = false;
225
- const nodes = await Promise.all(patched.map(async (patchedMessageWithJid) => {
226
- const { recipientJid: jid, ...patchedMessage } = patchedMessageWithJid;
227
- if (!jid) {
228
- return {};
229
- }
230
- const bytes = encodeWAMessage(patchedMessage);
231
- const { type, ciphertext } = await signalRepository.encryptMessage({ jid, data: bytes });
232
- if (type === 'pkmsg') {
233
- shouldIncludeDeviceIdentity = true;
234
- }
235
- const node = {
236
- tag: 'to',
237
- attrs: { jid },
238
- content: [
239
- {
240
- tag: 'enc',
241
- attrs: {
242
- v: '2',
243
- type,
244
- ...(extraAttrs || {})
245
- },
246
- content: ciphertext
247
- }
248
- ]
249
- };
341
+ const meId = authState.creds.me.id;
342
+ const meLid = authState.creds.me?.lid;
343
+ const meLidUser = meLid ? jidDecode(meLid)?.user : null;
344
+ const encryptionPromises = patchedMessages.map(async ({ recipientJid: jid, message: patchedMessage }) => {
345
+ if (!jid)
346
+ return null;
347
+ let msgToEncrypt = patchedMessage;
348
+ if (dsmMessage) {
349
+ const { user: targetUser } = jidDecode(jid);
350
+ const { user: ownPnUser } = jidDecode(meId);
351
+ const ownLidUser = meLidUser;
352
+ const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
353
+ const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
354
+ if (isOwnUser && !isExactSenderDevice) {
355
+ msgToEncrypt = dsmMessage;
356
+ logger.debug({ jid, targetUser }, 'Using DSM for own device');
357
+ }
358
+ }
359
+ const bytes = encodeWAMessage(msgToEncrypt);
360
+ const mutexKey = jid;
361
+ const node = await encryptionMutex.mutex(mutexKey, async () => {
362
+ const { type, ciphertext } = await signalRepository.encryptMessage({
363
+ jid,
364
+ data: bytes
365
+ });
366
+ if (type === 'pkmsg') {
367
+ shouldIncludeDeviceIdentity = true;
368
+ }
369
+ return {
370
+ tag: 'to',
371
+ attrs: { jid },
372
+ content: [
373
+ {
374
+ tag: 'enc',
375
+ attrs: {
376
+ v: '2',
377
+ type,
378
+ ...(extraAttrs || {})
379
+ },
380
+ content: ciphertext
381
+ }
382
+ ]
383
+ };
384
+ });
250
385
  return node;
251
- }));
386
+ });
387
+ const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
252
388
  return { nodes, shouldIncludeDeviceIdentity };
253
389
  };
254
390
  const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
255
391
  const meId = authState.creds.me.id;
256
- let shouldIncludeDeviceIdentity = false;
257
- const { user, server } = jidDecode(jid);
392
+ const meLid = authState.creds.me?.lid;
393
+ const isRetryResend = Boolean(participant?.jid);
394
+ let shouldIncludeDeviceIdentity = isRetryResend;
258
395
  const statusJid = 'status@broadcast';
396
+ const { user, server } = jidDecode(jid);
259
397
  const isGroup = server === 'g.us';
260
398
  const isStatus = jid === statusJid;
261
399
  const isLid = server === 'lid';
262
400
  const isNewsletter = server === 'newsletter';
263
- msgId = msgId || generateMessageIDV2(sock.user?.id);
401
+ const finalJid = jid;
402
+ msgId = msgId || generateMessageIDV2(meId);
264
403
  useUserDevicesCache = useUserDevicesCache !== false;
265
404
  useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
266
405
  const participants = [];
267
- const destinationJid = !isStatus ? jidEncode(user, isLid ? 'lid' : isGroup ? 'g.us' : 's.whatsapp.net') : statusJid;
406
+ const destinationJid = !isStatus ? finalJid : statusJid;
268
407
  const binaryNodeContent = [];
269
408
  const devices = [];
270
409
  const meMsg = {
@@ -276,14 +415,15 @@ export const makeMessagesSocket = (config) => {
276
415
  };
277
416
  const extraAttrs = {};
278
417
  if (participant) {
279
- // when the retry request is not for a group
280
- // only send to the specific device that asked for a retry
281
- // otherwise the message is sent out to every device that should be a recipient
282
418
  if (!isGroup && !isStatus) {
283
419
  additionalAttributes = { ...additionalAttributes, device_fanout: 'false' };
284
420
  }
285
421
  const { user, device } = jidDecode(participant.jid);
286
- devices.push({ user, device });
422
+ devices.push({
423
+ user,
424
+ device,
425
+ jid: participant.jid
426
+ });
287
427
  }
288
428
  await authState.keys.transaction(async () => {
289
429
  const mediaType = getMediaType(message);
@@ -291,7 +431,6 @@ export const makeMessagesSocket = (config) => {
291
431
  extraAttrs['mediatype'] = mediaType;
292
432
  }
293
433
  if (isNewsletter) {
294
- // Patch message if needed, then encode as plaintext
295
434
  const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
296
435
  const bytes = encodeNewsletterMessage(patched);
297
436
  binaryNodeContent.push({
@@ -314,117 +453,198 @@ export const makeMessagesSocket = (config) => {
314
453
  return;
315
454
  }
316
455
  if (normalizeMessageContent(message)?.pinInChatMessage) {
317
- extraAttrs['decrypt-fail'] = 'hide';
456
+ extraAttrs['decrypt-fail'] = 'hide'; // todo: expand for reactions and other types
318
457
  }
319
458
  if (isGroup || isStatus) {
320
459
  const [groupData, senderKeyMap] = await Promise.all([
321
460
  (async () => {
322
- let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined;
461
+ 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?
323
462
  if (groupData && Array.isArray(groupData?.participants)) {
324
463
  logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata');
325
464
  }
326
465
  else if (!isStatus) {
327
- groupData = await groupMetadata(jid);
466
+ groupData = await groupMetadata(jid); // TODO: start storing group participant list + addr mode in Signal & stop relying on this
328
467
  }
329
468
  return groupData;
330
469
  })(),
331
470
  (async () => {
332
471
  if (!participant && !isStatus) {
333
- const result = await authState.keys.get('sender-key-memory', [jid]);
472
+ // what if sender memory is less accurate than the cached metadata
473
+ // on participant change in group, we should do sender memory manipulation
474
+ 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?
334
475
  return result[jid] || {};
335
476
  }
336
477
  return {};
337
478
  })()
338
479
  ]);
339
480
  if (!participant) {
340
- const participantsList = groupData && !isStatus ? groupData.participants.map(p => p.id) : [];
341
- if (isStatus && statusJidList) {
342
- participantsList.push(...statusJidList);
481
+ const participantsList = [];
482
+ if (isStatus) {
483
+ if (statusJidList?.length)
484
+ participantsList.push(...statusJidList);
343
485
  }
344
- if (!isStatus) {
486
+ else {
487
+ // default to LID based groups
488
+ let groupAddressingMode = 'lid';
489
+ if (groupData) {
490
+ participantsList.push(...groupData.participants.map(p => p.id));
491
+ groupAddressingMode = groupData?.addressingMode || groupAddressingMode;
492
+ }
493
+ // default to lid addressing mode in a group
345
494
  additionalAttributes = {
346
495
  ...additionalAttributes,
347
- addressing_mode: groupData?.addressingMode || 'pn'
496
+ addressing_mode: groupAddressingMode
348
497
  };
349
498
  }
350
499
  const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false);
351
500
  devices.push(...additionalDevices);
352
501
  }
502
+ if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
503
+ additionalAttributes = {
504
+ ...additionalAttributes,
505
+ expiration: groupData.ephemeralDuration.toString()
506
+ };
507
+ }
353
508
  const patched = await patchMessageBeforeSending(message);
354
509
  if (Array.isArray(patched)) {
355
510
  throw new Boom('Per-jid patching is not supported in groups');
356
511
  }
357
512
  const bytes = encodeWAMessage(patched);
513
+ const groupAddressingMode = additionalAttributes?.['addressing_mode'] || groupData?.addressingMode || 'lid';
514
+ const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId;
358
515
  const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
359
516
  group: destinationJid,
360
517
  data: bytes,
361
- meId
518
+ meId: groupSenderIdentity
362
519
  });
363
- const senderKeyJids = [];
364
- // ensure a connection is established with every device
365
- for (const { user, device } of devices) {
366
- const jid = jidEncode(user, groupData?.addressingMode === 'lid' ? 'lid' : 's.whatsapp.net', device);
367
- if (!senderKeyMap[jid] || !!participant) {
368
- senderKeyJids.push(jid);
369
- // store that this person has had the sender keys sent to them
370
- senderKeyMap[jid] = true;
520
+ const senderKeyRecipients = [];
521
+ for (const device of devices) {
522
+ const deviceJid = device.jid;
523
+ const hasKey = !!senderKeyMap[deviceJid];
524
+ if ((!hasKey || !!participant) &&
525
+ !isHostedLidUser(deviceJid) &&
526
+ !isHostedPnUser(deviceJid) &&
527
+ device.device !== 99) {
528
+ //todo: revamp all this logic
529
+ // 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
530
+ senderKeyRecipients.push(deviceJid);
531
+ senderKeyMap[deviceJid] = true;
371
532
  }
372
533
  }
373
- // if there are some participants with whom the session has not been established
374
- // if there are, we re-send the senderkey
375
- if (senderKeyJids.length) {
376
- logger.debug({ senderKeyJids }, 'sending new sender key');
534
+ if (senderKeyRecipients.length) {
535
+ logger.debug({ senderKeyJids: senderKeyRecipients }, 'sending new sender key');
377
536
  const senderKeyMsg = {
378
537
  senderKeyDistributionMessage: {
379
538
  axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
380
539
  groupId: destinationJid
381
540
  }
382
541
  };
383
- await assertSessions(senderKeyJids, false);
384
- const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, extraAttrs);
542
+ const senderKeySessionTargets = senderKeyRecipients;
543
+ await assertSessions(senderKeySessionTargets);
544
+ const result = await createParticipantNodes(senderKeyRecipients, senderKeyMsg, extraAttrs);
385
545
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
386
546
  participants.push(...result.nodes);
387
547
  }
388
- binaryNodeContent.push({
389
- tag: 'enc',
390
- attrs: { v: '2', type: 'skmsg' },
391
- content: ciphertext
392
- });
393
- await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
548
+ if (isRetryResend) {
549
+ const { type, ciphertext: encryptedContent } = await signalRepository.encryptMessage({
550
+ data: bytes,
551
+ jid: participant?.jid
552
+ });
553
+ binaryNodeContent.push({
554
+ tag: 'enc',
555
+ attrs: {
556
+ v: '2',
557
+ type,
558
+ count: participant.count.toString()
559
+ },
560
+ content: encryptedContent
561
+ });
562
+ }
563
+ else {
564
+ binaryNodeContent.push({
565
+ tag: 'enc',
566
+ attrs: { v: '2', type: 'skmsg', ...extraAttrs },
567
+ content: ciphertext
568
+ });
569
+ await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
570
+ }
394
571
  }
395
572
  else {
396
- const { user: meUser } = jidDecode(meId);
573
+ // ADDRESSING CONSISTENCY: Match own identity to conversation context
574
+ // TODO: investigate if this is true
575
+ let ownId = meId;
576
+ if (isLid && meLid) {
577
+ ownId = meLid;
578
+ logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation');
579
+ }
580
+ else {
581
+ logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation');
582
+ }
583
+ const { user: ownUser } = jidDecode(ownId);
397
584
  if (!participant) {
398
- devices.push({ user });
399
- if (user !== meUser) {
400
- devices.push({ user: meUser });
585
+ const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
586
+ devices.push({
587
+ user,
588
+ device: 0,
589
+ jid: jidEncode(user, targetUserServer, 0) // rajeh, todo: this entire logic is convoluted and weird.
590
+ });
591
+ if (user !== ownUser) {
592
+ const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
593
+ const ownUserForAddressing = isLid && meLid ? jidDecode(meLid).user : jidDecode(meId).user;
594
+ devices.push({
595
+ user: ownUserForAddressing,
596
+ device: 0,
597
+ jid: jidEncode(ownUserForAddressing, ownUserServer, 0)
598
+ });
401
599
  }
402
600
  if (additionalAttributes?.['category'] !== 'peer') {
403
- const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true);
404
- devices.push(...additionalDevices);
601
+ // Clear placeholders and enumerate actual devices
602
+ devices.length = 0;
603
+ // Use conversation-appropriate sender identity
604
+ const senderIdentity = isLid && meLid
605
+ ? jidEncode(jidDecode(meLid)?.user, 'lid', undefined)
606
+ : jidEncode(jidDecode(meId)?.user, 's.whatsapp.net', undefined);
607
+ // Enumerate devices for sender and target with consistent addressing
608
+ const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false);
609
+ devices.push(...sessionDevices);
610
+ logger.debug({
611
+ deviceCount: devices.length,
612
+ devices: devices.map(d => `${d.user}:${d.device}@${jidDecode(d.jid)?.server}`)
613
+ }, 'Device enumeration complete with unified addressing');
405
614
  }
406
615
  }
407
- const allJids = [];
408
- const meJids = [];
409
- const otherJids = [];
410
- for (const { user, device } of devices) {
411
- const isMe = user === meUser;
412
- const jid = jidEncode(isMe && isLid ? authState.creds?.me?.lid.split(':')[0] || user : user, isLid ? 'lid' : 's.whatsapp.net', device);
616
+ const allRecipients = [];
617
+ const meRecipients = [];
618
+ const otherRecipients = [];
619
+ const { user: mePnUser } = jidDecode(meId);
620
+ const { user: meLidUser } = meLid ? jidDecode(meLid) : { user: null };
621
+ for (const { user, jid } of devices) {
622
+ const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
623
+ if (isExactSenderDevice) {
624
+ logger.debug({ jid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)');
625
+ continue;
626
+ }
627
+ // Check if this is our device (could match either PN or LID user)
628
+ const isMe = user === mePnUser || user === meLidUser;
413
629
  if (isMe) {
414
- meJids.push(jid);
630
+ meRecipients.push(jid);
415
631
  }
416
632
  else {
417
- otherJids.push(jid);
633
+ otherRecipients.push(jid);
418
634
  }
419
- allJids.push(jid);
635
+ allRecipients.push(jid);
420
636
  }
421
- await assertSessions(allJids, false);
637
+ await assertSessions(allRecipients);
422
638
  const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
423
- createParticipantNodes(meJids, meMsg, extraAttrs),
424
- createParticipantNodes(otherJids, message, extraAttrs)
639
+ // For own devices: use DSM if available (1:1 chats only)
640
+ createParticipantNodes(meRecipients, meMsg || message, extraAttrs),
641
+ createParticipantNodes(otherRecipients, message, extraAttrs, meMsg)
425
642
  ]);
426
643
  participants.push(...meNodes);
427
644
  participants.push(...otherNodes);
645
+ if (meRecipients.length > 0 || otherRecipients.length > 0) {
646
+ extraAttrs['phash'] = generateParticipantHashV2([...meRecipients, ...otherRecipients]);
647
+ }
428
648
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
429
649
  }
430
650
  if (participants.length) {
@@ -446,6 +666,7 @@ export const makeMessagesSocket = (config) => {
446
666
  tag: 'message',
447
667
  attrs: {
448
668
  id: msgId,
669
+ to: destinationJid,
449
670
  type: getMessageType(message),
450
671
  ...(additionalAttributes || {})
451
672
  },
@@ -485,13 +706,23 @@ export const makeMessagesSocket = (config) => {
485
706
  }
486
707
  logger.debug({ msgId }, `sending message to ${participants.length} devices`);
487
708
  await sendNode(stanza);
488
- });
709
+ // Add message to retry cache if enabled
710
+ if (messageRetryManager && !participant) {
711
+ messageRetryManager.addRecentMessage(destinationJid, msgId, message);
712
+ }
713
+ }, meId);
489
714
  return msgId;
490
715
  };
491
716
  const getMessageType = (message) => {
492
717
  if (message.pollCreationMessage || message.pollCreationMessageV2 || message.pollCreationMessageV3) {
493
718
  return 'poll';
494
719
  }
720
+ if (message.eventMessage) {
721
+ return 'event';
722
+ }
723
+ if (getMediaType(message) !== '') {
724
+ return 'media';
725
+ }
495
726
  return 'text';
496
727
  };
497
728
  const getMediaType = (message) => {
@@ -540,6 +771,7 @@ export const makeMessagesSocket = (config) => {
540
771
  else if (message.groupInviteMessage) {
541
772
  return 'url';
542
773
  }
774
+ return '';
543
775
  };
544
776
  const getPrivacyTokens = async (jids) => {
545
777
  const t = unixTimestampSeconds().toString();
@@ -583,6 +815,7 @@ export const makeMessagesSocket = (config) => {
583
815
  sendPeerDataOperationMessage,
584
816
  createParticipantNodes,
585
817
  getUSyncDevices,
818
+ messageRetryManager,
586
819
  updateMediaMessage: async (message) => {
587
820
  const content = assertMediaContent(message.message);
588
821
  const mediaKey = content.mediaKey;
@@ -647,19 +880,21 @@ export const makeMessagesSocket = (config) => {
647
880
  thumbnailWidth: linkPreviewImageThumbnailWidth,
648
881
  fetchOpts: {
649
882
  timeout: 3000,
650
- ...(axiosOptions || {})
883
+ ...(httpRequestOptions || {})
651
884
  },
652
885
  logger,
653
886
  uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
654
887
  }),
655
888
  //TODO: CACHE
656
889
  getProfilePicUrl: sock.profilePictureUrl,
890
+ getCallLink: sock.createCallLink,
657
891
  upload: waUploadToServer,
658
892
  mediaCache: config.mediaCache,
659
893
  options: config.options,
660
894
  messageId: options.messageId || generateMessageIDV2(sock.user?.id),
661
895
  ...options
662
896
  });
897
+ const isEventMsg = 'event' in content && !!content.event;
663
898
  const isDeleteMsg = 'delete' in content && !!content.delete;
664
899
  const isEditMsg = 'edit' in content && !!content.edit;
665
900
  const isPinMsg = 'pin' in content && !!content.pin;
@@ -690,8 +925,13 @@ export const makeMessagesSocket = (config) => {
690
925
  }
691
926
  });
692
927
  }
693
- if ('cachedGroupMetadata' in options) {
694
- console.warn('cachedGroupMetadata in sendMessage are deprecated, now cachedGroupMetadata is part of the socket config.');
928
+ else if (isEventMsg) {
929
+ additionalNodes.push({
930
+ tag: 'meta',
931
+ attrs: {
932
+ event_type: 'creation'
933
+ }
934
+ });
695
935
  }
696
936
  await relayMessage(jid, fullMsg.message, {
697
937
  messageId: fullMsg.key.id,