socketon 1.31.2-rc → 1.51.16

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 (213) hide show
  1. package/README.md +313 -159
  2. package/WAProto/WAProto.proto +5311 -0
  3. package/WAProto/index.js +65801 -141371
  4. package/lib/Defaults/index.js +117 -141
  5. package/lib/KeyDB/BinarySearch.js +20 -0
  6. package/lib/KeyDB/KeyedDB.js +167 -0
  7. package/lib/KeyDB/index.js +4 -0
  8. package/lib/Signal/Group/ciphertext-message.js +12 -14
  9. package/lib/Signal/Group/group-session-builder.js +10 -42
  10. package/lib/Signal/Group/group_cipher.js +75 -87
  11. package/lib/Signal/Group/index.js +13 -57
  12. package/lib/Signal/Group/keyhelper.js +17 -52
  13. package/lib/Signal/Group/sender-chain-key.js +27 -33
  14. package/lib/Signal/Group/sender-key-distribution-message.js +62 -63
  15. package/lib/Signal/Group/sender-key-message.js +65 -66
  16. package/lib/Signal/Group/sender-key-name.js +45 -44
  17. package/lib/Signal/Group/sender-key-record.js +39 -49
  18. package/lib/Signal/Group/sender-key-state.js +80 -93
  19. package/lib/Signal/Group/sender-message-key.js +27 -28
  20. package/lib/Signal/libsignal.js +313 -163
  21. package/lib/Signal/lid-mapping.js +155 -0
  22. package/lib/Socket/Client/index.js +4 -19
  23. package/lib/Socket/Client/types.js +13 -0
  24. package/lib/Socket/Client/websocket.js +52 -0
  25. package/lib/Socket/Client/websocket.js.bak +53 -0
  26. package/lib/Socket/business.js +359 -242
  27. package/lib/Socket/chats.js +846 -935
  28. package/lib/Socket/communities.js +413 -0
  29. package/lib/Socket/groups.js +304 -309
  30. package/lib/Socket/index.js +15 -10
  31. package/lib/Socket/messages-recv.js +1107 -1054
  32. package/lib/Socket/messages-send.js +639 -448
  33. package/lib/Socket/mex.js +45 -0
  34. package/lib/Socket/newsletter.js +240 -324
  35. package/lib/Socket/socket.js +794 -651
  36. package/lib/Socket/socketon.js +402 -0
  37. package/lib/Store/index.js +6 -10
  38. package/lib/Store/make-cache-manager-store.js +73 -81
  39. package/lib/Store/make-in-memory-store.js +286 -423
  40. package/lib/Store/make-ordered-dictionary.js +77 -79
  41. package/lib/Store/object-repository.js +24 -26
  42. package/lib/Types/Auth.js +3 -2
  43. package/lib/Types/Bussines.js +3 -0
  44. package/lib/Types/Call.js +3 -2
  45. package/lib/Types/Chat.js +9 -4
  46. package/lib/Types/Contact.js +3 -2
  47. package/lib/Types/Events.js +3 -2
  48. package/lib/Types/GroupMetadata.js +3 -2
  49. package/lib/Types/Label.js +24 -26
  50. package/lib/Types/LabelAssociation.js +6 -8
  51. package/lib/Types/Message.js +12 -9
  52. package/lib/Types/Newsletter.js +33 -38
  53. package/lib/Types/Newsletter.js.bak +33 -0
  54. package/lib/Types/Product.js +3 -2
  55. package/lib/Types/Signal.js +3 -2
  56. package/lib/Types/Socket.js +4 -2
  57. package/lib/Types/State.js +11 -2
  58. package/lib/Types/USync.js +3 -2
  59. package/lib/Types/index.js +27 -41
  60. package/lib/Utils/auth-utils.js +211 -198
  61. package/lib/Utils/baileys-event-stream.js +42 -61
  62. package/lib/Utils/browser-utils.js +25 -0
  63. package/lib/Utils/business.js +213 -214
  64. package/lib/Utils/chat-utils.js +710 -687
  65. package/lib/Utils/crypto.js +112 -133
  66. package/lib/Utils/decode-wa-message.js +252 -183
  67. package/lib/Utils/decode-wa-message.js.bak +267 -0
  68. package/lib/Utils/event-buffer.js +510 -496
  69. package/lib/Utils/generics.js +319 -392
  70. package/lib/Utils/history.js +83 -92
  71. package/lib/Utils/index.js +21 -33
  72. package/lib/Utils/link-preview.js +71 -83
  73. package/lib/Utils/logger.js +5 -7
  74. package/lib/Utils/lt-hash.js +40 -46
  75. package/lib/Utils/make-mutex.js +34 -41
  76. package/lib/Utils/message-retry-manager.js +113 -0
  77. package/lib/Utils/messages-media.js +550 -768
  78. package/lib/Utils/messages.js +354 -263
  79. package/lib/Utils/noise-handler.js +138 -149
  80. package/lib/Utils/pre-key-manager.js +85 -0
  81. package/lib/Utils/process-message.js +323 -303
  82. package/lib/Utils/signal.js +149 -141
  83. package/lib/Utils/use-multi-file-auth-state.js +95 -103
  84. package/lib/Utils/validate-connection.js +183 -214
  85. package/lib/WABinary/constants.js +1298 -35
  86. package/lib/WABinary/decode.js +237 -249
  87. package/lib/WABinary/encode.js +213 -260
  88. package/lib/WABinary/generic-utils.js +56 -65
  89. package/lib/WABinary/index.js +7 -21
  90. package/lib/WABinary/jid-utils.js +89 -58
  91. package/lib/WABinary/types.js +3 -2
  92. package/lib/WAM/BinaryInfo.js +10 -12
  93. package/lib/WAM/constants.js +22851 -15348
  94. package/lib/WAM/encode.js +135 -136
  95. package/lib/WAM/index.js +5 -19
  96. package/lib/WAUSync/Protocols/USyncContactProtocol.js +28 -30
  97. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +49 -53
  98. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -28
  99. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +36 -39
  100. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -50
  101. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +26 -20
  102. package/lib/WAUSync/Protocols/index.js +6 -20
  103. package/lib/WAUSync/USyncQuery.js +86 -85
  104. package/lib/WAUSync/USyncUser.js +23 -25
  105. package/lib/WAUSync/index.js +5 -19
  106. package/lib/index.js +27 -35
  107. package/package.json +85 -95
  108. package/engine-requirements.js +0 -10
  109. package/lib/Defaults/baileys-version.json +0 -3
  110. package/lib/Defaults/index.d.ts +0 -53
  111. package/lib/Defaults/phonenumber-mcc.json +0 -223
  112. package/lib/Signal/Group/ciphertext-message.d.ts +0 -9
  113. package/lib/Signal/Group/group-session-builder.d.ts +0 -14
  114. package/lib/Signal/Group/group_cipher.d.ts +0 -17
  115. package/lib/Signal/Group/index.d.ts +0 -11
  116. package/lib/Signal/Group/keyhelper.d.ts +0 -10
  117. package/lib/Signal/Group/queue-job.d.ts +0 -1
  118. package/lib/Signal/Group/queue-job.js +0 -57
  119. package/lib/Signal/Group/sender-chain-key.d.ts +0 -13
  120. package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -16
  121. package/lib/Signal/Group/sender-key-message.d.ts +0 -18
  122. package/lib/Signal/Group/sender-key-name.d.ts +0 -17
  123. package/lib/Signal/Group/sender-key-record.d.ts +0 -30
  124. package/lib/Signal/Group/sender-key-state.d.ts +0 -38
  125. package/lib/Signal/Group/sender-message-key.d.ts +0 -11
  126. package/lib/Signal/libsignal.d.ts +0 -3
  127. package/lib/Socket/Client/abstract-socket-client.d.ts +0 -17
  128. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  129. package/lib/Socket/Client/index.d.ts +0 -3
  130. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  131. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  132. package/lib/Socket/Client/web-socket-client.d.ts +0 -12
  133. package/lib/Socket/Client/web-socket-client.js +0 -62
  134. package/lib/Socket/business.d.ts +0 -171
  135. package/lib/Socket/chats.d.ts +0 -267
  136. package/lib/Socket/dugong.d.ts +0 -254
  137. package/lib/Socket/dugong.js +0 -484
  138. package/lib/Socket/groups.d.ts +0 -115
  139. package/lib/Socket/index.d.ts +0 -173
  140. package/lib/Socket/messages-recv.d.ts +0 -161
  141. package/lib/Socket/messages-send.d.ts +0 -149
  142. package/lib/Socket/newsletter.d.ts +0 -134
  143. package/lib/Socket/registration.d.ts +0 -267
  144. package/lib/Socket/registration.js +0 -166
  145. package/lib/Socket/socket.d.ts +0 -43
  146. package/lib/Socket/usync.d.ts +0 -36
  147. package/lib/Socket/usync.js +0 -70
  148. package/lib/Store/index.d.ts +0 -3
  149. package/lib/Store/make-cache-manager-store.d.ts +0 -13
  150. package/lib/Store/make-in-memory-store.d.ts +0 -118
  151. package/lib/Store/make-ordered-dictionary.d.ts +0 -13
  152. package/lib/Store/object-repository.d.ts +0 -10
  153. package/lib/Types/Auth.d.ts +0 -110
  154. package/lib/Types/Call.d.ts +0 -13
  155. package/lib/Types/Chat.d.ts +0 -102
  156. package/lib/Types/Contact.d.ts +0 -19
  157. package/lib/Types/Events.d.ts +0 -157
  158. package/lib/Types/GroupMetadata.d.ts +0 -55
  159. package/lib/Types/Label.d.ts +0 -35
  160. package/lib/Types/LabelAssociation.d.ts +0 -29
  161. package/lib/Types/Message.d.ts +0 -273
  162. package/lib/Types/Newsletter.d.ts +0 -103
  163. package/lib/Types/Product.d.ts +0 -78
  164. package/lib/Types/Signal.d.ts +0 -57
  165. package/lib/Types/Socket.d.ts +0 -111
  166. package/lib/Types/State.d.ts +0 -27
  167. package/lib/Types/USync.d.ts +0 -25
  168. package/lib/Types/index.d.ts +0 -57
  169. package/lib/Utils/auth-utils.d.ts +0 -18
  170. package/lib/Utils/baileys-event-stream.d.ts +0 -16
  171. package/lib/Utils/business.d.ts +0 -22
  172. package/lib/Utils/chat-utils.d.ts +0 -71
  173. package/lib/Utils/crypto.d.ts +0 -41
  174. package/lib/Utils/decode-wa-message.d.ts +0 -19
  175. package/lib/Utils/event-buffer.d.ts +0 -35
  176. package/lib/Utils/generics.d.ts +0 -92
  177. package/lib/Utils/generics.js.bak +0 -433
  178. package/lib/Utils/history.d.ts +0 -15
  179. package/lib/Utils/index.d.ts +0 -17
  180. package/lib/Utils/link-preview.d.ts +0 -21
  181. package/lib/Utils/logger.d.ts +0 -4
  182. package/lib/Utils/lt-hash.d.ts +0 -12
  183. package/lib/Utils/make-mutex.d.ts +0 -7
  184. package/lib/Utils/messages-media.d.ts +0 -116
  185. package/lib/Utils/messages.d.ts +0 -77
  186. package/lib/Utils/noise-handler.d.ts +0 -21
  187. package/lib/Utils/process-message.d.ts +0 -41
  188. package/lib/Utils/signal.d.ts +0 -32
  189. package/lib/Utils/use-multi-file-auth-state.d.ts +0 -13
  190. package/lib/Utils/validate-connection.d.ts +0 -11
  191. package/lib/Utils/validate-connection.js.bak +0 -237
  192. package/lib/WABinary/constants.d.ts +0 -30
  193. package/lib/WABinary/decode.d.ts +0 -7
  194. package/lib/WABinary/encode.d.ts +0 -3
  195. package/lib/WABinary/generic-utils.d.ts +0 -17
  196. package/lib/WABinary/index.d.ts +0 -5
  197. package/lib/WABinary/jid-utils.d.ts +0 -31
  198. package/lib/WABinary/types.d.ts +0 -18
  199. package/lib/WAM/BinaryInfo.d.ts +0 -17
  200. package/lib/WAM/constants.d.ts +0 -38
  201. package/lib/WAM/encode.d.ts +0 -3
  202. package/lib/WAM/index.d.ts +0 -3
  203. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -9
  204. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -22
  205. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -12
  206. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -12
  207. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +0 -25
  208. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +0 -8
  209. package/lib/WAUSync/Protocols/index.d.ts +0 -4
  210. package/lib/WAUSync/USyncQuery.d.ts +0 -28
  211. package/lib/WAUSync/USyncUser.d.ts +0 -12
  212. package/lib/WAUSync/index.d.ts +0 -3
  213. package/lib/index.d.ts +0 -12
@@ -1,68 +1,89 @@
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 newsletter_1 = require("./newsletter");
17
- const WAUSync_1 = require("../WAUSync")
18
- const kikyy = require('./dugong');
19
- var ListType = WAProto_1.proto.Message.ListMessage.ListType;
20
- const makeMessagesSocket = (config) => {
21
- const {
22
- logger,
23
- linkPreviewImageThumbnailWidth,
24
- generateHighQualityLinkPreview,
25
- options: axiosOptions,
26
- patchMessageBeforeSending
27
- } = config;
28
- const sock = (0, newsletter_1.makeNewsletterSocket)(config);
29
- const {
30
- ev,
31
- authState,
32
- processingMutex,
33
- signalRepository,
34
- upsertMessage,
35
- query,
36
- fetchPrivacySettings,
37
- generateMessageTag,
38
- sendNode,
39
- groupMetadata,
40
- groupToggleEphemeral,
41
- executeUSyncQuery
42
- } = sock;
43
- const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
44
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
1
+ import NodeCache from '@cacheable/node-cache';
2
+ import { Boom } from '@hapi/boom';
3
+ import { proto } from '../../WAProto/index.js';
4
+ import {
5
+ DEFAULT_CACHE_TTLS,
6
+ WA_DEFAULT_EPHEMERAL
7
+ } from '../Defaults/index.js';
8
+ import {
9
+ aggregateMessageKeysNotFromMe,
10
+ assertMediaContent,
11
+ bindWaitForEvent,
12
+ decryptMediaRetryData,
13
+ encodeNewsletterMessage,
14
+ encodeSignedDeviceIdentity,
15
+ encodeWAMessage,
16
+ encryptMediaRetryRequest,
17
+ extractDeviceJids,
18
+ generateMessageIDV2,
19
+ generateParticipantHashV2,
20
+ generateWAMessage,
21
+ getStatusCodeForMediaRetry,
22
+ getUrlFromDirectPath,
23
+ getWAUploadToServer,
24
+ MessageRetryManager,
25
+ normalizeMessageContent,
26
+ parseAndInjectE2ESessions,
27
+ unixTimestampSeconds
28
+ } from '../Utils/index.js';
29
+ import {
30
+ areJidsSameUser,
31
+ getBinaryNodeChild,
32
+ getBinaryNodeChildren,
33
+ getAdditionalNode,
34
+ getBinaryNodeFilter,
35
+ isHostedLidUser,
36
+ isHostedPnUser,
37
+ isJidGroup,
38
+ isLidUser,
39
+ isPnUser,
40
+ jidDecode,
41
+ jidEncode,
42
+ isJidNewsletter,
43
+ jidNormalizedUser,
44
+ S_WHATSAPP_NET
45
+ } from '../WABinary/index.js';
46
+ import { getUrlInfo } from '../Utils/link-preview.js';
47
+ import { makeKeyedMutex } from '../Utils/make-mutex.js';
48
+ import { USyncQuery, USyncUser } from '../WAUSync/index.js';
49
+ import { makeNewsletterSocket } from './newsletter.js';
50
+ export const makeMessagesSocket = (config) => {
51
+ const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
52
+ const sock = makeNewsletterSocket(config);
53
+ const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral } = sock;
54
+ const userDevicesCache = config.userDevicesCache ||
55
+ new NodeCache({
56
+ stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
57
+ useClones: false
58
+ });
59
+ const peerSessionsCache = new NodeCache({
60
+ stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES,
45
61
  useClones: false
46
62
  });
63
+ // Initialize message retry manager if enabled
64
+ const messageRetryManager = enableRecentMessageCache ? new MessageRetryManager(logger, maxMsgRetryCount) : null;
65
+ // Prevent race conditions in Signal session encryption by user
66
+ const encryptionMutex = makeKeyedMutex();
47
67
  let mediaConn;
48
68
  const refreshMediaConn = async (forceGet = false) => {
49
69
  const media = await mediaConn;
50
- if (!media || forceGet || (new Date().getTime() - media.fetchDate.getTime()) > media.ttl * 1000) {
70
+ if (!media || forceGet || new Date().getTime() - media.fetchDate.getTime() > media.ttl * 1000) {
51
71
  mediaConn = (async () => {
52
72
  const result = await query({
53
73
  tag: 'iq',
54
74
  attrs: {
55
75
  type: 'set',
56
76
  xmlns: 'w:m',
57
- to: WABinary_1.S_WHATSAPP_NET,
77
+ to: S_WHATSAPP_NET
58
78
  },
59
79
  content: [{ tag: 'media_conn', attrs: {} }]
60
80
  });
61
- const mediaConnNode = WABinary_1.getBinaryNodeChild(result, 'media_conn');
81
+ const mediaConnNode = getBinaryNodeChild(result, 'media_conn');
82
+ // TODO: explore full length of data that whatsapp provides
62
83
  const node = {
63
- hosts: WABinary_1.getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
84
+ hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
64
85
  hostname: attrs.hostname,
65
- maxContentLengthBytes: +attrs.maxContentLengthBytes,
86
+ maxContentLengthBytes: +attrs.maxContentLengthBytes
66
87
  })),
67
88
  auth: mediaConnNode.attrs.auth,
68
89
  ttl: +mediaConnNode.attrs.ttl,
@@ -79,17 +100,20 @@ const makeMessagesSocket = (config) => {
79
100
  * used for receipts of phone call, read, delivery etc.
80
101
  * */
81
102
  const sendReceipt = async (jid, participant, messageIds, type) => {
103
+ if (!messageIds || messageIds.length === 0) {
104
+ throw new Boom('missing ids in receipt');
105
+ }
82
106
  const node = {
83
107
  tag: 'receipt',
84
108
  attrs: {
85
- id: messageIds[0],
86
- },
109
+ id: messageIds[0]
110
+ }
87
111
  };
88
112
  const isReadReceipt = type === 'read' || type === 'read-self';
89
113
  if (isReadReceipt) {
90
- node.attrs.t = (0, Utils_1.unixTimestampSeconds)().toString();
114
+ node.attrs.t = unixTimestampSeconds().toString();
91
115
  }
92
- if (type === 'sender' && WABinary_1.isJidUser(jid)) {
116
+ if (type === 'sender' && (isPnUser(jid) || isLidUser(jid))) {
93
117
  node.attrs.recipient = jid;
94
118
  node.attrs.to = participant;
95
119
  }
@@ -100,7 +124,7 @@ const makeMessagesSocket = (config) => {
100
124
  }
101
125
  }
102
126
  if (type) {
103
- node.attrs.type = WABinary_1.isJidNewsLetter(jid) ? 'read-self' : type;
127
+ node.attrs.type = type;
104
128
  }
105
129
  const remainingMessageIds = messageIds.slice(1);
106
130
  if (remainingMessageIds.length) {
@@ -120,7 +144,7 @@ const makeMessagesSocket = (config) => {
120
144
  };
121
145
  /** Correctly bulk send receipts to multiple chats, participants */
122
146
  const sendReceipts = async (keys, type) => {
123
- const recps = (0, Utils_1.aggregateMessageKeysNotFromMe)(keys);
147
+ const recps = aggregateMessageKeysNotFromMe(keys);
124
148
  for (const { jid, participant, messageIds } of recps) {
125
149
  await sendReceipt(jid, participant, messageIds, type);
126
150
  }
@@ -134,207 +158,349 @@ const makeMessagesSocket = (config) => {
134
158
  };
135
159
  /** Fetch all the devices we've to send a message to */
136
160
  const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
137
- const deviceResults = []
138
-
161
+ const deviceResults = [];
139
162
  if (!useCache) {
140
- logger.debug('not using cache for devices')
163
+ logger.debug('not using cache for devices');
141
164
  }
142
-
143
- const toFetch = []
144
-
145
- jids = Array.from(new Set(jids))
146
-
147
- for (let jid of jids) {
148
- const user = WABinary_1.jidDecode(jid)?.user
149
-
150
- jid = WABinary_1.jidNormalizedUser(jid)
151
-
165
+ const toFetch = [];
166
+ const jidsWithUser = jids
167
+ .map(jid => {
168
+ const decoded = jidDecode(jid);
169
+ const user = decoded?.user;
170
+ const device = decoded?.device;
171
+ const isExplicitDevice = typeof device === 'number' && device >= 0;
172
+ if (isExplicitDevice && user) {
173
+ deviceResults.push({
174
+ user,
175
+ device,
176
+ jid
177
+ });
178
+ return null;
179
+ }
180
+ jid = jidNormalizedUser(jid);
181
+ return { jid, user };
182
+ })
183
+ .filter(jid => jid !== null);
184
+ let mgetDevices;
185
+ if (useCache && userDevicesCache.mget) {
186
+ const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean);
187
+ mgetDevices = await userDevicesCache.mget(usersToFetch);
188
+ }
189
+ for (const { jid, user } of jidsWithUser) {
152
190
  if (useCache) {
153
- const devices = userDevicesCache.get(user)
154
-
191
+ const devices = mgetDevices?.[user] ||
192
+ (userDevicesCache.mget ? undefined : (await userDevicesCache.get(user)));
155
193
  if (devices) {
156
- deviceResults.push(...devices)
157
- logger.trace({ user }, 'using cache for devices')
194
+ const devicesWithJid = devices.map(d => ({
195
+ ...d,
196
+ jid: jidEncode(d.user, d.server, d.device)
197
+ }));
198
+ deviceResults.push(...devicesWithJid);
199
+ logger.trace({ user }, 'using cache for devices');
158
200
  }
159
-
160
201
  else {
161
- toFetch.push(jid)
202
+ toFetch.push(jid);
162
203
  }
163
204
  }
164
-
165
205
  else {
166
- toFetch.push(jid)
206
+ toFetch.push(jid);
167
207
  }
168
208
  }
169
-
170
209
  if (!toFetch.length) {
171
- return deviceResults
210
+ return deviceResults;
172
211
  }
173
-
174
- const query = new WAUSync_1.USyncQuery()
175
- .withContext('message')
176
- .withDeviceProtocol()
177
-
212
+ const requestedLidUsers = new Set();
178
213
  for (const jid of toFetch) {
179
- query.withUser(new WAUSync_1.USyncUser().withId(jid))
214
+ if (isLidUser(jid) || isHostedLidUser(jid)) {
215
+ const user = jidDecode(jid)?.user;
216
+ if (user)
217
+ requestedLidUsers.add(user);
218
+ }
180
219
  }
181
-
182
- const result = await executeUSyncQuery(query)
183
-
220
+ const query = new USyncQuery().withContext('message').withDeviceProtocol().withLIDProtocol();
221
+ for (const jid of toFetch) {
222
+ 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
223
+ }
224
+ const result = await sock.executeUSyncQuery(query);
184
225
  if (result) {
185
- const extracted = Utils_1.extractDeviceJids(result?.list, authState.creds.me.id, ignoreZeroDevices)
186
- const deviceMap = {}
187
-
226
+ // TODO: LID MAP this stuff (lid protocol will now return lid with devices)
227
+ const lidResults = result.list.filter(a => !!a.lid);
228
+ if (lidResults.length > 0) {
229
+ logger.trace('Storing LID maps from device call');
230
+ await signalRepository.lidMapping.storeLIDPNMappings(lidResults.map(a => ({ lid: a.lid, pn: a.id })));
231
+ }
232
+ const extracted = extractDeviceJids(result?.list, authState.creds.me.id, authState.creds.me.lid, ignoreZeroDevices);
233
+ const deviceMap = {};
188
234
  for (const item of extracted) {
189
- deviceMap[item.user] = deviceMap[item.user] || []
190
- deviceMap[item.user].push(item)
191
- deviceResults.push(item)
235
+ deviceMap[item.user] = deviceMap[item.user] || [];
236
+ deviceMap[item.user]?.push(item);
192
237
  }
193
-
194
- for (const key in deviceMap) {
195
- userDevicesCache.set(key, deviceMap[key])
238
+ // Process each user's devices as a group for bulk LID migration
239
+ for (const [user, userDevices] of Object.entries(deviceMap)) {
240
+ const isLidUser = requestedLidUsers.has(user);
241
+ // Process all devices for this user
242
+ for (const item of userDevices) {
243
+ const finalJid = isLidUser
244
+ ? jidEncode(user, item.server, item.device)
245
+ : jidEncode(item.user, item.server, item.device);
246
+ deviceResults.push({
247
+ ...item,
248
+ jid: finalJid
249
+ });
250
+ logger.debug({
251
+ user: item.user,
252
+ device: item.device,
253
+ finalJid,
254
+ usedLid: isLidUser
255
+ }, 'Processed device with LID priority');
256
+ }
257
+ }
258
+ if (userDevicesCache.mset) {
259
+ // if the cache supports mset, we can set all devices in one go
260
+ await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })));
261
+ }
262
+ else {
263
+ for (const key in deviceMap) {
264
+ if (deviceMap[key])
265
+ await userDevicesCache.set(key, deviceMap[key]);
266
+ }
267
+ }
268
+ const userDeviceUpdates = {};
269
+ for (const [userId, devices] of Object.entries(deviceMap)) {
270
+ if (devices && devices.length > 0) {
271
+ userDeviceUpdates[userId] = devices.map(d => d.device?.toString() || '0');
272
+ }
273
+ }
274
+ if (Object.keys(userDeviceUpdates).length > 0) {
275
+ try {
276
+ await authState.keys.set({ 'device-list': userDeviceUpdates });
277
+ logger.debug({ userCount: Object.keys(userDeviceUpdates).length }, 'stored user device lists for bulk migration');
278
+ }
279
+ catch (error) {
280
+ logger.warn({ error }, 'failed to store user device lists');
281
+ }
196
282
  }
197
283
  }
198
-
199
- return deviceResults
200
- }
201
- const assertSessions = async (jids, force) => {
284
+ return deviceResults;
285
+ };
286
+ const assertSessions = async (jids) => {
202
287
  let didFetchNewSession = false;
203
- let jidsRequiringFetch = [];
204
- if (force) {
205
- jidsRequiringFetch = jids;
206
- }
207
- else {
208
- const addrs = jids.map(jid => (signalRepository
209
- .jidToSignalProtocolAddress(jid)));
210
- const sessions = await authState.keys.get('session', addrs);
211
- for (const jid of jids) {
212
- const signalId = signalRepository
213
- .jidToSignalProtocolAddress(jid);
214
- if (!sessions[signalId]) {
215
- jidsRequiringFetch.push(jid);
288
+ const uniqueJids = [...new Set(jids)]; // Deduplicate JIDs
289
+ const jidsRequiringFetch = [];
290
+ logger.debug({ jids }, 'assertSessions call with jids');
291
+ // Check peerSessionsCache and validate sessions using libsignal loadSession
292
+ for (const jid of uniqueJids) {
293
+ const signalId = signalRepository.jidToSignalProtocolAddress(jid);
294
+ const cachedSession = peerSessionsCache.get(signalId);
295
+ if (cachedSession !== undefined) {
296
+ if (cachedSession) {
297
+ continue; // Session exists in cache
298
+ }
299
+ }
300
+ else {
301
+ const sessionValidation = await signalRepository.validateSession(jid);
302
+ const hasSession = sessionValidation.exists;
303
+ peerSessionsCache.set(signalId, hasSession);
304
+ if (hasSession) {
305
+ continue;
216
306
  }
217
307
  }
308
+ jidsRequiringFetch.push(jid);
218
309
  }
219
310
  if (jidsRequiringFetch.length) {
220
- logger.debug({ jidsRequiringFetch }, 'fetching sessions');
311
+ // LID if mapped, otherwise original
312
+ const wireJids = [
313
+ ...jidsRequiringFetch.filter(jid => !!isLidUser(jid) || !!isHostedLidUser(jid)),
314
+ ...((await signalRepository.lidMapping.getLIDsForPNs(jidsRequiringFetch.filter(jid => !!isPnUser(jid) || !!isHostedPnUser(jid)))) || []).map(a => a.lid)
315
+ ];
316
+ logger.debug({ jidsRequiringFetch, wireJids }, 'fetching sessions');
221
317
  const result = await query({
222
318
  tag: 'iq',
223
319
  attrs: {
224
320
  xmlns: 'encrypt',
225
321
  type: 'get',
226
- to: WABinary_1.S_WHATSAPP_NET,
322
+ to: S_WHATSAPP_NET
227
323
  },
228
324
  content: [
229
325
  {
230
326
  tag: 'key',
231
327
  attrs: {},
232
- content: jidsRequiringFetch.map(jid => ({
328
+ content: wireJids.map(jid => ({
233
329
  tag: 'user',
234
- attrs: { jid },
330
+ attrs: { jid }
235
331
  }))
236
332
  }
237
333
  ]
238
334
  });
239
- await (0, Utils_1.parseAndInjectE2ESessions)(result, signalRepository);
335
+ await parseAndInjectE2ESessions(result, signalRepository);
240
336
  didFetchNewSession = true;
337
+ // Cache fetched sessions using wire JIDs
338
+ for (const wireJid of wireJids) {
339
+ const signalId = signalRepository.jidToSignalProtocolAddress(wireJid);
340
+ peerSessionsCache.set(signalId, true);
341
+ }
241
342
  }
242
343
  return didFetchNewSession;
243
344
  };
244
-
245
-
246
345
  const sendPeerDataOperationMessage = async (pdoMessage) => {
346
+ //TODO: for later, abstract the logic to send a Peer Message instead of just PDO - useful for App State Key Resync with phone
247
347
  if (!authState.creds.me?.id) {
248
- throw new boom_1.Boom('Not authenticated')
348
+ throw new Boom('Not authenticated');
249
349
  }
250
-
251
350
  const protocolMessage = {
252
351
  protocolMessage: {
253
352
  peerDataOperationRequestMessage: pdoMessage,
254
- type: WAProto_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
353
+ type: proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
255
354
  }
256
355
  };
257
- const meJid = WABinary_1.jidNormalizedUser(authState.creds.me.id);
356
+ const meJid = jidNormalizedUser(authState.creds.me.id);
258
357
  const msgId = await relayMessage(meJid, protocolMessage, {
259
358
  additionalAttributes: {
260
359
  category: 'peer',
261
- // eslint-disable-next-line camelcase
262
- push_priority: 'high_force',
360
+ push_priority: 'high_force'
263
361
  },
362
+ additionalNodes: [
363
+ {
364
+ tag: 'meta',
365
+ attrs: { appdata: 'default' }
366
+ }
367
+ ]
264
368
  });
265
369
  return msgId;
266
370
  };
267
- const createParticipantNodes = async (jids, message, extraAttrs) => {
268
- const patched = await patchMessageBeforeSending(message, jids);
269
- const bytes = (0, Utils_1.encodeWAMessage)(patched);
371
+ const createParticipantNodes = async (recipientJids, message, extraAttrs, dsmMessage) => {
372
+ if (!recipientJids.length) {
373
+ return { nodes: [], shouldIncludeDeviceIdentity: false };
374
+ }
375
+ const patched = await patchMessageBeforeSending(message, recipientJids);
376
+ const patchedMessages = Array.isArray(patched)
377
+ ? patched
378
+ : recipientJids.map(jid => ({ recipientJid: jid, message: patched }));
270
379
  let shouldIncludeDeviceIdentity = false;
271
- const nodes = await Promise.all(jids.map(async (jid) => {
272
- const { type, ciphertext } = await signalRepository
273
- .encryptMessage({ jid, data: bytes });
274
- if (type === 'pkmsg') {
275
- shouldIncludeDeviceIdentity = true;
276
- }
277
- const node = {
278
- tag: 'to',
279
- attrs: { jid },
280
- content: [{
281
- tag: 'enc',
282
- attrs: {
283
- v: '2',
284
- type,
285
- ...extraAttrs || {}
286
- },
287
- content: ciphertext
288
- }]
289
- };
380
+ const meId = authState.creds.me.id;
381
+ const meLid = authState.creds.me?.lid;
382
+ const meLidUser = meLid ? jidDecode(meLid)?.user : null;
383
+ const encryptionPromises = patchedMessages.map(async ({ recipientJid: jid, message: patchedMessage }) => {
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({
402
+ jid,
403
+ data: bytes
404
+ });
405
+ if (type === 'pkmsg') {
406
+ shouldIncludeDeviceIdentity = true;
407
+ }
408
+ return {
409
+ tag: 'to',
410
+ attrs: { jid },
411
+ content: [
412
+ {
413
+ tag: 'enc',
414
+ attrs: {
415
+ v: '2',
416
+ type,
417
+ ...(extraAttrs || {})
418
+ },
419
+ content: ciphertext
420
+ }
421
+ ]
422
+ };
423
+ });
290
424
  return node;
291
- }));
425
+ });
426
+ const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
292
427
  return { nodes, shouldIncludeDeviceIdentity };
293
- }; //apela
294
- const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, cachedGroupMetadata, useCachedGroupMetadata, statusJidList, AI = false }) => {
295
- const meId = authState.creds.me.id;
296
- let shouldIncludeDeviceIdentity = false;
428
+ };
429
+ const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, AI = false }) => {
430
+ // let shouldIncludeDeviceIdentity = false;
297
431
  let didPushAdditional = false
298
- const { user, server } = WABinary_1.jidDecode(jid);
432
+ const meId = authState.creds.me.id;
433
+ const meLid = authState.creds.me?.lid;
434
+ const isRetryResend = Boolean(participant?.jid);
435
+ let shouldIncludeDeviceIdentity = isRetryResend;
299
436
  const statusJid = 'status@broadcast';
437
+ const { user, server } = jidDecode(jid);
300
438
  const isGroup = server === 'g.us';
301
439
  const isStatus = jid === statusJid;
302
440
  const isLid = server === 'lid';
303
- const isPrivate = server === 's.whatsapp.net'
304
441
  const isNewsletter = server === 'newsletter';
305
- msgId = msgId || (0, Utils_1.generateMessageID)();
442
+ const isPrivate = server === 's.whatsapp.net'
443
+ const finalJid = jid;
444
+ msgId = msgId || generateMessageIDV2(meId);
306
445
  useUserDevicesCache = useUserDevicesCache !== false;
307
- useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
446
+ useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
308
447
  const participants = [];
309
- const destinationJid = (!isStatus) ? WABinary_1.jidEncode(user, isLid ? 'lid' : isGroup ? 'g.us' : isNewsletter ? 'newsletter' : 's.whatsapp.net') : statusJid;
448
+ const destinationJid = !isStatus ? finalJid : statusJid;
310
449
  const binaryNodeContent = [];
311
450
  const devices = [];
312
451
  const meMsg = {
313
452
  deviceSentMessage: {
314
453
  destinationJid,
315
454
  message
316
- }
455
+ },
456
+ messageContextInfo: message.messageContextInfo
317
457
  };
318
- const extraAttrs = {}
319
- const messages = Utils_1.normalizeMessageContent(message)
458
+ const extraAttrs = {};
459
+ const messages = normalizeMessageContent(message)
320
460
  const buttonType = getButtonType(messages);
321
461
  if (participant) {
322
- // when the retry request is not for a group
323
- // only send to the specific device that asked for a retry
324
- // otherwise the message is sent out to every device that should be a recipient
325
462
  if (!isGroup && !isStatus) {
326
- additionalAttributes = { ...additionalAttributes, 'device_fanout': 'false' };
463
+ additionalAttributes = {
464
+ ...additionalAttributes,
465
+ device_fanout: 'false'
466
+ };
327
467
  }
328
- const { user, device } = WABinary_1.jidDecode(participant.jid);
329
- devices.push({ user, device });
468
+ const { user, device } = jidDecode(participant.jid);
469
+ devices.push({
470
+ user,
471
+ device,
472
+ jid: participant.jid
473
+ });
330
474
  }
331
475
  await authState.keys.transaction(async () => {
332
- const mediaType = getMediaType(messages);
333
-
476
+ const mediaType = getMediaType(message);
334
477
  if (mediaType) {
335
- extraAttrs['mediatype'] = mediaType
478
+ extraAttrs['mediatype'] = mediaType;
336
479
  }
337
480
 
481
+ if (isNewsletter) {
482
+ const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
483
+ const bytes = encodeNewsletterMessage(patched);
484
+ binaryNodeContent.push({
485
+ tag: "plaintext",
486
+ attrs: mediaType ? { mediatype: mediaType } : {},
487
+ content: bytes
488
+ });
489
+ const stanza = {
490
+ tag: "message",
491
+ attrs: {
492
+ to: jid,
493
+ id: msgId,
494
+ type: getTypeMessage(message),
495
+ ...(additionalAttributes || {})
496
+ },
497
+ content: binaryNodeContent
498
+ };
499
+ logger.debug({ msgId }, `sending newsletter message to ${jid}`);
500
+ await sendNode(stanza);
501
+ return;
502
+ }
503
+
338
504
  if (messages.pinInChatMessage || messages.keepInChatMessage || message.reactionMessage || message.protocolMessage?.editedMessage) {
339
505
  extraAttrs['decrypt-fail'] = 'hide'
340
506
  }
@@ -346,185 +512,228 @@ const makeMessagesSocket = (config) => {
346
512
  if (isGroup || isStatus) {
347
513
  const [groupData, senderKeyMap] = await Promise.all([
348
514
  (async () => {
349
- let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined
350
- if (groupData) {
351
- logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata');
515
+ 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?
516
+ if (groupData && Array.isArray(groupData?.participants)) {
517
+ logger.trace({
518
+ jid,
519
+ participants: groupData.participants.length
520
+ }, 'using cached group metadata');
352
521
  }
353
-
354
522
  else if (!isStatus) {
355
- groupData = await groupMetadata(jid)
523
+ groupData = await groupMetadata(jid); // TODO: start storing group participant list + addr mode in Signal & stop relying on this
356
524
  }
357
-
358
525
  return groupData;
359
526
  })(),
360
527
  (async () => {
361
528
  if (!participant && !isStatus) {
362
- const result = await authState.keys.get('sender-key-memory', [jid])
363
- return result[jid] || {}
529
+ // what if sender memory is less accurate than the cached metadata
530
+ // on participant change in group, we should do sender memory manipulation
531
+ 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?
532
+ return result[jid] || {};
364
533
  }
365
-
366
- return {}
367
-
368
- })()
534
+ return {};
535
+ })()
369
536
  ]);
370
537
  if (!participant) {
371
- const participantsList = (groupData && !isStatus) ? groupData.participants.map(p => p.id) : []
372
-
538
+ const participantsList = groupData && !isStatus ? groupData.participants.map(p => p.id) : [];
373
539
  if (isStatus && statusJidList) {
374
- participantsList.push(...statusJidList)
540
+ participantsList.push(...statusJidList);
375
541
  }
376
-
377
- // if (!isStatus) {
378
- // const expiration = await getEphemeralGroup(jid)
379
- // additionalAttributes = {
380
- // ...additionalAttributes,
381
- // addressing_mode: 'pn',
382
- // ...expiration ? { expiration: expiration.toString() } : null
383
- // }
384
- // }
385
-
386
- const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false)
387
- devices.push(...additionalDevices)
542
+ // if (!isStatus) {
543
+ // additionalAttributes = {
544
+ // ...additionalAttributes,
545
+ // addressing_mode: groupData?.addressingMode || 'pn'
546
+ // };
547
+ // }
548
+ const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false);
549
+ devices.push(...additionalDevices);
388
550
  }
389
-
390
- const patched = await patchMessageBeforeSending(message, devices.map(d => WABinary_1.jidEncode(d.user, isLid ? 'lid' : 's.whatsapp.net', d.device)));
391
- const bytes = Utils_1.encodeWAMessage(patched);
392
-
551
+ if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
552
+ additionalAttributes = {
553
+ ...additionalAttributes,
554
+ expiration: groupData.ephemeralDuration.toString()
555
+ };
556
+ }
557
+ const patched = await patchMessageBeforeSending(message);
558
+ if (Array.isArray(patched)) {
559
+ throw new Boom('Per-jid patching is not supported in groups');
560
+ }
561
+ const bytes = encodeWAMessage(patched);
562
+ const groupAddressingMode = additionalAttributes?.['addressing_mode'] || groupData?.addressingMode || 'lid';
563
+ const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId;
393
564
  const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
394
565
  group: destinationJid,
395
566
  data: bytes,
396
- meId,
567
+ meId: groupSenderIdentity
397
568
  });
398
- const senderKeyJids = [];
399
-
400
- for (const { user, device } of devices) {
401
- const jid = WABinary_1.jidEncode(user, (groupData === null || groupData === void 0 ? void 0 : groupData.addressingMode) === 'lid' ? 'lid' : 's.whatsapp.net', device);
402
- if (!senderKeyMap[jid] || !!participant) {
403
- senderKeyJids.push(jid);
404
- // store that this person has had the sender keys sent to them
405
- senderKeyMap[jid] = true;
569
+ const senderKeyRecipients = [];
570
+ for (const device of devices) {
571
+ const deviceJid = device.jid;
572
+ const hasKey = !!senderKeyMap[deviceJid];
573
+ if ((!hasKey || !!participant) &&
574
+ !isHostedLidUser(deviceJid) &&
575
+ !isHostedPnUser(deviceJid) &&
576
+ device.device !== 99) {
577
+ //todo: revamp all this logic
578
+ // 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
579
+ senderKeyRecipients.push(deviceJid);
580
+ senderKeyMap[deviceJid] = true;
406
581
  }
407
582
  }
408
- // if there are some participants with whom the session has not been established
409
- // if there are, we re-send the senderkey
410
- if (senderKeyJids.length) {
411
- logger.debug({ senderKeyJids }, 'sending new sender key');
583
+ if (senderKeyRecipients.length) {
584
+ logger.debug({ senderKeyJids: senderKeyRecipients }, 'sending new sender key');
412
585
  const senderKeyMsg = {
413
586
  senderKeyDistributionMessage: {
414
587
  axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
415
588
  groupId: destinationJid
416
589
  }
417
590
  };
418
- await assertSessions(senderKeyJids, false);
419
- const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, extraAttrs)
591
+ const senderKeySessionTargets = senderKeyRecipients;
592
+ await assertSessions(senderKeySessionTargets);
593
+ const result = await createParticipantNodes(senderKeyRecipients, senderKeyMsg, extraAttrs);
420
594
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
421
595
  participants.push(...result.nodes);
422
596
  }
423
- binaryNodeContent.push({
424
- tag: 'enc',
425
- attrs: { v: '2', type: 'skmsg', ...extraAttrs },
426
- content: ciphertext
427
- });
428
- await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
429
- }
430
- else if (isNewsletter) {
431
- // Message edit
432
- if (message.protocolMessage?.editedMessage) {
433
- msgId = message.protocolMessage.key?.id
434
- message = message.protocolMessage.editedMessage
597
+ if (isRetryResend) {
598
+ const { type, ciphertext: encryptedContent } = await signalRepository.encryptMessage({
599
+ data: bytes,
600
+ jid: participant?.jid
601
+ });
602
+ binaryNodeContent.push({
603
+ tag: 'enc',
604
+ attrs: {
605
+ v: '2',
606
+ type,
607
+ count: participant.count.toString()
608
+ },
609
+ content: encryptedContent
610
+ });
435
611
  }
436
-
437
- // Message delete
438
- if (message.protocolMessage?.type === WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE) {
439
- msgId = message.protocolMessage.key?.id
440
- message = {}
612
+ else {
613
+ binaryNodeContent.push({
614
+ tag: 'enc',
615
+ attrs: {
616
+ v: '2',
617
+ type: 'skmsg',
618
+ ...extraAttrs
619
+ },
620
+ content: ciphertext
621
+ });
622
+ await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
441
623
  }
442
-
443
- const patched = await patchMessageBeforeSending(message, [])
444
- const bytes = Utils_1.encodeNewsletterMessage(patched)
445
-
446
- binaryNodeContent.push({
447
- tag: 'plaintext',
448
- attrs: extraAttrs ? extraAttrs : {},
449
- content: bytes
450
- })
451
624
  }
452
625
  else {
453
- const { user: meUser } = WABinary_1.jidDecode(meId);
626
+ // ADDRESSING CONSISTENCY: Match own identity to conversation context
627
+ // TODO: investigate if this is true
628
+ let ownId = meId;
629
+ if (isLid && meLid) {
630
+ ownId = meLid;
631
+ logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation');
632
+ }
633
+ else {
634
+ logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation');
635
+ }
636
+ const { user: ownUser } = jidDecode(ownId);
454
637
  if (!participant) {
455
- devices.push({ user })
456
- if (user !== meUser) {
457
- devices.push({ user: meUser })
638
+ const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
639
+ devices.push({
640
+ user,
641
+ device: 0,
642
+ jid: jidEncode(user, targetUserServer, 0) // rajeh, todo: this entire logic is convoluted and weird.
643
+ });
644
+ if (user !== ownUser) {
645
+ const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
646
+ const ownUserForAddressing = isLid && meLid ? jidDecode(meLid).user : jidDecode(meId).user;
647
+ devices.push({
648
+ user: ownUserForAddressing,
649
+ device: 0,
650
+ jid: jidEncode(ownUserForAddressing, ownUserServer, 0)
651
+ });
458
652
  }
459
-
460
653
  if (additionalAttributes?.['category'] !== 'peer') {
461
- const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true)
462
-
463
- devices.push(...additionalDevices)
654
+ // Clear placeholders and enumerate actual devices
655
+ devices.length = 0;
656
+ // Use conversation-appropriate sender identity
657
+ const senderIdentity = isLid && meLid
658
+ ? jidEncode(jidDecode(meLid)?.user, 'lid', undefined)
659
+ : jidEncode(jidDecode(meId)?.user, 's.whatsapp.net', undefined);
660
+ // Enumerate devices for sender and target with consistent addressing
661
+ const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false);
662
+ devices.push(...sessionDevices);
663
+ logger.debug({
664
+ deviceCount: devices.length,
665
+ devices: devices.map(d => `${d.user}:${d.device}@${jidDecode(d.jid)?.server}`)
666
+ }, 'Device enumeration complete with unified addressing');
464
667
  }
465
668
  }
466
- const allJids = [];
467
- const meJids = [];
468
- const otherJids = [];
469
- for (const { user, device } of devices) {
470
- const isMe = user === meUser
471
- const jid = WABinary_1.jidEncode(isMe && isLid ? authState.creds?.me?.lid?.split(':')[0] || user : user, isLid ? 'lid' : 's.whatsapp.net', device)
472
-
669
+ const allRecipients = [];
670
+ const meRecipients = [];
671
+ const otherRecipients = [];
672
+ const { user: mePnUser } = jidDecode(meId);
673
+ const { user: meLidUser } = meLid ? jidDecode(meLid) : { user: null };
674
+ for (const { user, jid } of devices) {
675
+ const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
676
+ if (isExactSenderDevice) {
677
+ logger.debug({ jid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)');
678
+ continue;
679
+ }
680
+ // Check if this is our device (could match either PN or LID user)
681
+ const isMe = user === mePnUser || user === meLidUser;
473
682
  if (isMe) {
474
- meJids.push(jid)
683
+ meRecipients.push(jid);
475
684
  }
476
-
477
685
  else {
478
- otherJids.push(jid)
686
+ otherRecipients.push(jid);
479
687
  }
480
-
481
- allJids.push(jid)
688
+ allRecipients.push(jid);
482
689
  }
483
- await assertSessions(allJids, false);
690
+ await assertSessions(allRecipients);
484
691
  const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
485
- createParticipantNodes(meJids, meMsg, extraAttrs),
486
- createParticipantNodes(otherJids, message, extraAttrs)
487
- ])
692
+ // For own devices: use DSM if available (1:1 chats only)
693
+ createParticipantNodes(meRecipients, meMsg || message, extraAttrs),
694
+ createParticipantNodes(otherRecipients, message, extraAttrs, meMsg)
695
+ ]);
488
696
  participants.push(...meNodes);
489
697
  participants.push(...otherNodes);
698
+ /* if (meRecipients.length > 0 || otherRecipients.length > 0) {
699
+ extraAttrs['phash'] = generateParticipantHashV2([...meRecipients, ...otherRecipients]);
700
+ }*/
490
701
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
491
702
  }
492
703
  if (participants.length) {
493
704
  if (additionalAttributes?.['category'] === 'peer') {
494
- const peerNode = participants[0]?.content?.[0]
495
-
705
+ const peerNode = participants[0]?.content?.[0];
496
706
  if (peerNode) {
497
- binaryNodeContent.push(peerNode) // push only enc
707
+ binaryNodeContent.push(peerNode); // push only enc
498
708
  }
499
709
  }
500
-
501
710
  else {
502
711
  binaryNodeContent.push({
503
712
  tag: 'participants',
504
713
  attrs: {},
505
714
  content: participants
506
- })
715
+ });
507
716
  }
508
717
  }
509
-
510
718
  const stanza = {
511
719
  tag: 'message',
512
720
  attrs: {
513
721
  id: msgId,
514
- type: getTypeMessage(messages),
722
+ to: destinationJid,
723
+ type: getTypeMessage(messages),
515
724
  ...(additionalAttributes || {})
516
725
  },
517
726
  content: binaryNodeContent
518
- }
727
+ };
519
728
  // if the participant to send to is explicitly specified (generally retry recp)
520
729
  // ensure the message is only sent to that person
521
730
  // if a retry receipt is sent to everyone -- it'll fail decryption for everyone else who received the msg
522
731
  if (participant) {
523
- if (WABinary_1.isJidGroup(destinationJid)) {
732
+ if (isJidGroup(destinationJid)) {
524
733
  stanza.attrs.to = destinationJid;
525
734
  stanza.attrs.participant = participant.jid;
526
735
  }
527
- else if (WABinary_1.areJidsSameUser(participant.jid, meId)) {
736
+ else if (areJidsSameUser(participant.jid, meId)) {
528
737
  stanza.attrs.to = participant.jid;
529
738
  stanza.attrs.recipient = destinationJid;
530
739
  }
@@ -536,14 +745,14 @@ const makeMessagesSocket = (config) => {
536
745
  stanza.attrs.to = destinationJid;
537
746
  }
538
747
  if (shouldIncludeDeviceIdentity) {
748
+ ;
539
749
  stanza.content.push({
540
750
  tag: 'device-identity',
541
751
  attrs: {},
542
- content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
752
+ content: encodeSignedDeviceIdentity(authState.creds.account, true)
543
753
  });
544
754
  logger.debug({ jid }, 'adding device identity');
545
755
  }
546
-
547
756
  if (AI && isPrivate) {
548
757
  const botNode = {
549
758
  tag: 'bot',
@@ -552,7 +761,7 @@ const makeMessagesSocket = (config) => {
552
761
  }
553
762
  }
554
763
 
555
- const filteredBizBot = WABinary_1.getBinaryNodeFilter(additionalNodes ? additionalNodes : [])
764
+ const filteredBizBot = getBinaryNodeFilter(additionalNodes ? additionalNodes : [])
556
765
 
557
766
  if (filteredBizBot) {
558
767
  stanza.content.push(...additionalNodes)
@@ -564,9 +773,9 @@ const makeMessagesSocket = (config) => {
564
773
  }
565
774
  }
566
775
 
567
- if(!isNewsletter && buttonType && !isStatus) {
568
- const content = WABinary_1.getAdditionalNode(buttonType)
569
- const filteredNode = WABinary_1.getBinaryNodeFilter(additionalNodes)
776
+ if(buttonType && !isStatus) {
777
+ const content = getAdditionalNode(buttonType)
778
+ const filteredNode = getBinaryNodeFilter(additionalNodes)
570
779
 
571
780
  if (filteredNode) {
572
781
  didPushAdditional = true
@@ -581,42 +790,44 @@ const makeMessagesSocket = (config) => {
581
790
  if (!didPushAdditional && additionalNodes && additionalNodes.length > 0) {
582
791
  stanza.content.push(...additionalNodes);
583
792
  }
584
-
585
793
  logger.debug({ msgId }, `sending message to ${participants.length} devices`);
586
794
  await sendNode(stanza);
587
- });
588
-
589
- message = Types_1.WAProto.Message.fromObject(message)
590
-
591
- const messageJSON = {
592
- key: {
593
- remoteJid: jid,
594
- fromMe: true,
595
- id: msgId
596
- },
597
- message: message,
598
- messageTimestamp: Utils_1.unixTimestampSeconds(new Date()),
599
- messageStubParameters: [],
600
- participant: WABinary_1.isJidGroup(jid) || WABinary_1.isJidStatusBroadcast(jid) ? meId : undefined,
601
- status: Types_1.WAMessageStatus.PENDING
602
- }
603
-
604
- return Types_1.WAProto.WebMessageInfo.fromObject(messageJSON)
605
- // return msgId;
795
+ // Add message to retry cache if enabled
796
+ if (messageRetryManager && !participant) {
797
+ messageRetryManager.addRecentMessage(destinationJid, msgId, message);
798
+ }
799
+ }, meId);
800
+ return msgId;
606
801
  };
607
802
  const getTypeMessage = (msg) => {
608
- const message = Utils_1.normalizeMessageContent(msg)
609
- if (message.reactionMessage) {
610
- return 'reaction'
611
- }
612
- else if (getMediaType(message)) {
613
- return 'media'
614
- }
803
+ if (msg.viewOnceMessage) {
804
+ return getTypeMessage(msg.viewOnceMessage.message);
805
+ }
806
+ else if (msg.viewOnceMessageV2) {
807
+ return getTypeMessage(msg.viewOnceMessageV2.message);
808
+ }
809
+ else if (msg.viewOnceMessageV2Extension) {
810
+ return getTypeMessage(msg.viewOnceMessageV2Extension.message);
811
+ }
812
+ else if (msg.ephemeralMessage) {
813
+ return getTypeMessage(msg.ephemeralMessage.message);
814
+ }
815
+ else if (msg.documentWithCaptionMessage) {
816
+ return getTypeMessage(msg.documentWithCaptionMessage.message);
817
+ }
818
+ else if (msg.reactionMessage) {
819
+ return 'reaction';
820
+ }
821
+ else if (msg.pollCreationMessage || msg.pollCreationMessageV2 || msg.pollCreationMessageV3 || msg.pollUpdateMessage) {
822
+ return 'poll';
823
+ }
824
+ else if (getMediaType(msg)) {
825
+ return 'media';
826
+ }
615
827
  else {
616
- return 'text'
828
+ return 'text';
617
829
  }
618
- }
619
-
830
+ };
620
831
  const getMediaType = (message) => {
621
832
  if (message.imageMessage) {
622
833
  return 'image'
@@ -666,8 +877,7 @@ const makeMessagesSocket = (config) => {
666
877
  else if (/https:\/\/wa\.me\/p\/\d+\/\d+/.test(message.extendedTextMessage?.text)) {
667
878
  return 'productlink'
668
879
  }
669
- }
670
-
880
+ }
671
881
  const getButtonType = (message) => {
672
882
  if (message.listMessage) {
673
883
  return 'list'
@@ -698,11 +908,11 @@ const makeMessagesSocket = (config) => {
698
908
  }
699
909
  }
700
910
  const getPrivacyTokens = async (jids) => {
701
- const t = Utils_1.unixTimestampSeconds().toString();
911
+ const t = unixTimestampSeconds().toString();
702
912
  const result = await query({
703
913
  tag: 'iq',
704
914
  attrs: {
705
- to: WABinary_1.S_WHATSAPP_NET,
915
+ to: S_WHATSAPP_NET,
706
916
  type: 'set',
707
917
  xmlns: 'privacy'
708
918
  },
@@ -713,7 +923,7 @@ const makeMessagesSocket = (config) => {
713
923
  content: jids.map(jid => ({
714
924
  tag: 'token',
715
925
  attrs: {
716
- jid: WABinary_1.jidNormalizedUser(jid),
926
+ jid: jidNormalizedUser(jid),
717
927
  t,
718
928
  type: 'trusted_contact'
719
929
  }
@@ -722,10 +932,9 @@ const makeMessagesSocket = (config) => {
722
932
  ]
723
933
  });
724
934
  return result;
725
- }
726
- const waUploadToServer = (0, Utils_1.getWAUploadToServer)(config, refreshMediaConn);
727
- const rahmi = new kikyy(Utils_1, waUploadToServer, relayMessage);
728
- const waitForMsgMediaUpdate = (0, Utils_1.bindWaitForEvent)(ev, 'messages.media-update');
935
+ };
936
+ const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
937
+ const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
729
938
  return {
730
939
  ...sock,
731
940
  getPrivacyTokens,
@@ -733,23 +942,23 @@ const makeMessagesSocket = (config) => {
733
942
  relayMessage,
734
943
  sendReceipt,
735
944
  sendReceipts,
736
- rahmi,
737
945
  readMessages,
738
946
  refreshMediaConn,
739
- getUSyncDevices,
740
- createParticipantNodes,
741
947
  waUploadToServer,
742
- sendPeerDataOperationMessage,
743
948
  fetchPrivacySettings,
949
+ sendPeerDataOperationMessage,
950
+ createParticipantNodes,
951
+ getUSyncDevices,
952
+ messageRetryManager,
744
953
  updateMediaMessage: async (message) => {
745
- const content = (0, Utils_1.assertMediaContent)(message.message);
954
+ const content = assertMediaContent(message.message);
746
955
  const mediaKey = content.mediaKey;
747
956
  const meId = authState.creds.me.id;
748
- const node = (0, Utils_1.encryptMediaRetryRequest)(message.key, mediaKey, meId);
957
+ const node = await encryptMediaRetryRequest(message.key, mediaKey, meId);
749
958
  let error = undefined;
750
959
  await Promise.all([
751
960
  sendNode(node),
752
- waitForMsgMediaUpdate(update => {
961
+ waitForMsgMediaUpdate(async (update) => {
753
962
  const result = update.find(c => c.key.id === message.key.id);
754
963
  if (result) {
755
964
  if (result.error) {
@@ -757,13 +966,16 @@ const makeMessagesSocket = (config) => {
757
966
  }
758
967
  else {
759
968
  try {
760
- const media = (0, Utils_1.decryptMediaRetryData)(result.media, mediaKey, result.key.id);
761
- if (media.result !== WAProto_1.proto.MediaRetryNotification.ResultType.SUCCESS) {
762
- const resultStr = WAProto_1.proto.MediaRetryNotification.ResultType[media.result];
763
- throw new boom_1.Boom(`Media re-upload failed by device (${resultStr})`, { data: media, statusCode: (0, Utils_1.getStatusCodeForMediaRetry)(media.result) || 404 });
969
+ const media = await decryptMediaRetryData(result.media, mediaKey, result.key.id);
970
+ if (media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
971
+ const resultStr = proto.MediaRetryNotification.ResultType[media.result];
972
+ throw new Boom(`Media re-upload failed by device (${resultStr})`, {
973
+ data: media,
974
+ statusCode: getStatusCodeForMediaRetry(media.result) || 404
975
+ });
764
976
  }
765
977
  content.directPath = media.directPath;
766
- content.url = (0, Utils_1.getUrlFromDirectPath)(content.directPath);
978
+ content.url = getUrlFromDirectPath(content.directPath);
767
979
  logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful');
768
980
  }
769
981
  catch (err) {
@@ -777,133 +989,112 @@ const makeMessagesSocket = (config) => {
777
989
  if (error) {
778
990
  throw error;
779
991
  }
780
- ev.emit('messages.update', [
781
- {
782
- key: message.key,
783
- update: {
784
- message: message.message
785
- }
786
- }
787
- ]);
992
+ ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
788
993
  return message;
789
994
  },
790
995
  sendMessage: async (jid, content, options = {}) => {
791
996
  const userJid = authState.creds.me.id;
792
- delete options.ephemeralExpiration
793
- const { filter = false, quoted } = options;
794
- const getParticipantAttr = () => filter ? { participant: { jid } } : {};
795
- const messageType = rahmi.detectType(content);
796
- if (typeof content === 'object' && 'disappearingMessagesInChat' in content &&
797
- typeof content['disappearingMessagesInChat'] !== 'undefined' && WABinary_1.isJidGroup(jid)) {
798
- const { disappearingMessagesInChat } = content
799
-
800
- const value = typeof disappearingMessagesInChat === 'boolean' ?
801
- (disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
802
- disappearingMessagesInChat
803
-
804
- await groupToggleEphemeral(jid, value)
997
+ if (typeof content === 'object' &&
998
+ 'disappearingMessagesInChat' in content &&
999
+ typeof content['disappearingMessagesInChat'] !== 'undefined' &&
1000
+ isJidGroup(jid)) {
1001
+ const { disappearingMessagesInChat } = content;
1002
+ const value = typeof disappearingMessagesInChat === 'boolean'
1003
+ ? disappearingMessagesInChat
1004
+ ? WA_DEFAULT_EPHEMERAL
1005
+ : 0
1006
+ : disappearingMessagesInChat;
1007
+ await groupToggleEphemeral(jid, value);
805
1008
  }
806
-
807
1009
  else {
808
- let mediaHandle
809
-
810
-
811
- if (messageType) {
812
- switch(messageType) {
813
- case 'PAYMENT':
814
- const paymentContent = await rahmi.handlePayment(content, quoted);
815
- return await relayMessage(jid, paymentContent, {
816
- messageId: Utils_1.generateMessageID(),
817
- ...getParticipantAttr()
818
- });
819
-
820
- case 'PRODUCT':
821
- const productContent = await rahmi.handleProduct(content, jid, quoted);
822
- const productMsg = await Utils_1.generateWAMessageFromContent(jid, productContent, { quoted });
823
- return await relayMessage(jid, productMsg.message, {
824
- messageId: productMsg.key.id,
825
- ...getParticipantAttr()
826
- });
827
-
828
- case 'INTERACTIVE':
829
- const interactiveContent = await rahmi.handleInteractive(content, jid, quoted);
830
- const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted });
831
- return await relayMessage(jid, interactiveMsg.message, {
832
- messageId: interactiveMsg.key.id,
833
- ...getParticipantAttr()
1010
+ const fullMsg = await generateWAMessage(jid, content, {
1011
+ logger,
1012
+ userJid,
1013
+ getUrlInfo: text => getUrlInfo(text, {
1014
+ thumbnailWidth: linkPreviewImageThumbnailWidth,
1015
+ fetchOpts: {
1016
+ timeout: 3000,
1017
+ ...(httpRequestOptions || {})
1018
+ },
1019
+ logger,
1020
+ uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
1021
+ }),
1022
+ //TODO: CACHE
1023
+ getProfilePicUrl: sock.profilePictureUrl,
1024
+ getCallLink: sock.createCallLink,
1025
+ upload: async (readStream, opts) => {
1026
+ const up = await waUploadToServer(readStream, {
1027
+ ...opts,
1028
+ newsletter: isJidNewsletter(jid)
834
1029
  });
835
- case 'ALBUM':
836
- return await rahmi.handleAlbum(content, jid, quoted)
837
- case 'EVENT':
838
- return await rahmi.handleEvent(content, jid, quoted)
839
- case 'POLL_RESULT':
840
- return await rahmi.handlePollResult(content, jid, quoted)
841
- case 'GROUP_STORY':
842
- return await rahmi.handleGroupStory(content, jid, quoted)
843
- }
844
- }
845
- const fullMsg = await Utils_1.generateWAMessage(jid, content, {
846
- logger,
847
- userJid,
848
- quoted,
849
- getUrlInfo: text => link_preview_1.getUrlInfo(text, {
850
- thumbnailWidth: linkPreviewImageThumbnailWidth,
851
- fetchOpts: {
852
- timeout: 3000,
853
- ...axiosOptions || {}
1030
+ return up;
854
1031
  },
855
- logger,
856
- uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
857
- }),
858
- upload: async (readStream, opts) => {
859
- const up = await waUploadToServer(readStream, {
860
- ...opts,
861
- newsletter: WABinary_1.isJidNewsLetter(jid)
862
- });
863
- return up;
864
- },
865
- mediaCache: config.mediaCache,
866
- options: config.options,
867
- ...options
868
- });
869
-
870
- const isDeleteMsg = 'delete' in content && !!content.delete;
871
- const isEditMsg = 'edit' in content && !!content.edit;
872
- const isAiMsg = 'ai' in content && !!content.ai;
873
-
874
- const additionalAttributes = {};
875
- const additionalNodes = [];
876
-
877
- if (isDeleteMsg) {
878
- const fromMe = content.delete?.fromMe;
879
- const isGroup = WABinary_1.isJidGroup(content.delete?.remoteJid);
880
- additionalAttributes.edit = (isGroup && !fromMe) || WABinary_1.isJidNewsLetter(jid) ? '8' : '7';
881
- } else if (isEditMsg) {
882
- additionalAttributes.edit = WABinary_1.isJidNewsLetter(jid) ? '3' : '1';
883
- } else if (isAiMsg) {
884
- additionalNodes.push({
1032
+ mediaCache: config.mediaCache,
1033
+ options: config.options,
1034
+ messageId: generateMessageIDV2(sock.user?.id),
1035
+ ...options
1036
+ });
1037
+ const isAiMsg = 'ai' in content && !!content.ai;
1038
+ const isEventMsg = 'event' in content && !!content.event;
1039
+ const isDeleteMsg = 'delete' in content && !!content.delete;
1040
+ const isEditMsg = 'edit' in content && !!content.edit;
1041
+ const isPinMsg = 'pin' in content && !!content.pin;
1042
+ const isPollMessage = 'poll' in content && !!content.poll;
1043
+ const additionalAttributes = {};
1044
+ const additionalNodes = [];
1045
+ // required for delete
1046
+ if (isDeleteMsg) {
1047
+ // if the chat is a group, and I am not the author, then delete the message as an admin
1048
+ if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
1049
+ additionalAttributes.edit = '8';
1050
+ }
1051
+ else {
1052
+ additionalAttributes.edit = '7';
1053
+ }
1054
+ }
1055
+ else if (isEditMsg) {
1056
+ additionalAttributes.edit = '1';
1057
+ }
1058
+ else if (isAiMsg) {
1059
+ additionalNodes.push({
885
1060
  attrs: {
886
1061
  biz_bot: '1'
887
1062
  }, tag: "bot"
888
1063
  });
889
- }
890
-
891
- await relayMessage(jid, fullMsg.message, {
892
- messageId: fullMsg.key.id,
893
- cachedGroupMetadata: options.cachedGroupMetadata,
894
- additionalNodes: isAiMsg ? additionalNodes : options.additionalNodes,
895
- additionalAttributes,
896
- statusJidList: options.statusJidList
897
- });
898
-
899
- if (config.emitOwnEvents) {
900
- process.nextTick(() => {
901
- processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1064
+ }
1065
+ else if (isPinMsg) {
1066
+ additionalAttributes.edit = '2';
1067
+ }
1068
+ else if (isPollMessage) {
1069
+ additionalNodes.push({
1070
+ tag: 'meta',
1071
+ attrs: {
1072
+ polltype: 'creation'
1073
+ }
1074
+ });
1075
+ }
1076
+ else if (isEventMsg) {
1077
+ additionalNodes.push({
1078
+ tag: 'meta',
1079
+ attrs: {
1080
+ event_type: 'creation'
1081
+ }
1082
+ });
1083
+ }
1084
+ await relayMessage(jid, fullMsg.message, {
1085
+ messageId: fullMsg.key.id,
1086
+ useCachedGroupMetadata: options.useCachedGroupMetadata,
1087
+ additionalAttributes,
1088
+ statusJidList: options.statusJidList,
1089
+ additionalNodes: isAiMsg ? additionalNodes : options.additionalNodes
902
1090
  });
903
- }
904
- return fullMsg;
1091
+ if (config.emitOwnEvents) {
1092
+ process.nextTick(() => {
1093
+ processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1094
+ });
1095
+ }
1096
+ return fullMsg;
905
1097
  }
906
1098
  }
907
- }
908
- };
909
- exports.makeMessagesSocket = makeMessagesSocket;
1099
+ };
1100
+ };