@dyyxyzz/baileys-mod 6.0.53 → 7.0.4

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/LICENSE +21 -0
  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/Defaults/index.js.bak +123 -0
  6. package/lib/KeyDB/BinarySearch.js +20 -0
  7. package/lib/KeyDB/KeyedDB.js +167 -0
  8. package/lib/KeyDB/index.js +4 -0
  9. package/lib/Signal/Group/ciphertext-message.js +12 -14
  10. package/lib/Signal/Group/group-session-builder.js +10 -42
  11. package/lib/Signal/Group/group_cipher.js +75 -87
  12. package/lib/Signal/Group/index.js +13 -57
  13. package/lib/Signal/Group/keyhelper.js +17 -52
  14. package/lib/Signal/Group/sender-chain-key.js +27 -33
  15. package/lib/Signal/Group/sender-key-distribution-message.js +62 -63
  16. package/lib/Signal/Group/sender-key-message.js +65 -66
  17. package/lib/Signal/Group/sender-key-name.js +45 -44
  18. package/lib/Signal/Group/sender-key-record.js +39 -49
  19. package/lib/Signal/Group/sender-key-state.js +80 -93
  20. package/lib/Signal/Group/sender-message-key.js +27 -28
  21. package/lib/Signal/libsignal.js +313 -163
  22. package/lib/Signal/lid-mapping.js +155 -0
  23. package/lib/Socket/Client/index.js +4 -19
  24. package/lib/Socket/Client/types.js +13 -0
  25. package/lib/Socket/Client/websocket.js +52 -0
  26. package/lib/Socket/Client/websocket.js.bak +53 -0
  27. package/lib/Socket/business.js +359 -242
  28. package/lib/Socket/chats.js +839 -943
  29. package/lib/Socket/communities.js +413 -0
  30. package/lib/Socket/groups.js +304 -309
  31. package/lib/Socket/index.js +15 -10
  32. package/lib/Socket/messages-recv.js +1107 -1054
  33. package/lib/Socket/messages-send.js +639 -449
  34. package/lib/Socket/mex.js +45 -0
  35. package/lib/Socket/newsletter.js +197 -311
  36. package/lib/Socket/socket.js +5 -3
  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 +5 -1
  63. package/lib/Utils/business.js +213 -214
  64. package/lib/Utils/chat-utils.js +703 -689
  65. package/lib/Utils/crypto.js +112 -133
  66. package/lib/Utils/decode-wa-message.js +252 -183
  67. package/lib/Utils/event-buffer.js +510 -496
  68. package/lib/Utils/generics.js +319 -392
  69. package/lib/Utils/history.js +83 -92
  70. package/lib/Utils/index.js +21 -33
  71. package/lib/Utils/link-preview.js +71 -83
  72. package/lib/Utils/logger.js +5 -7
  73. package/lib/Utils/lt-hash.js +40 -46
  74. package/lib/Utils/make-mutex.js +34 -41
  75. package/lib/Utils/message-retry-manager.js +113 -0
  76. package/lib/Utils/messages-media.js +550 -768
  77. package/lib/Utils/messages.js +371 -270
  78. package/lib/Utils/noise-handler.js +138 -149
  79. package/lib/Utils/pre-key-manager.js +85 -0
  80. package/lib/Utils/process-message.js +323 -303
  81. package/lib/Utils/signal.js +149 -141
  82. package/lib/Utils/use-multi-file-auth-state.js +95 -103
  83. package/lib/Utils/validate-connection.js +183 -214
  84. package/lib/WABinary/constants.js +1298 -35
  85. package/lib/WABinary/decode.js +237 -249
  86. package/lib/WABinary/encode.js +213 -260
  87. package/lib/WABinary/generic-utils.js +56 -65
  88. package/lib/WABinary/index.js +7 -21
  89. package/lib/WABinary/jid-utils.js +89 -58
  90. package/lib/WABinary/types.js +3 -2
  91. package/lib/WAM/BinaryInfo.js +10 -12
  92. package/lib/WAM/constants.js +22851 -15348
  93. package/lib/WAM/encode.js +135 -136
  94. package/lib/WAM/index.js +5 -19
  95. package/lib/WAUSync/Protocols/USyncContactProtocol.js +28 -30
  96. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +49 -53
  97. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -28
  98. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +36 -39
  99. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -50
  100. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +26 -20
  101. package/lib/WAUSync/Protocols/index.js +6 -20
  102. package/lib/WAUSync/USyncQuery.js +86 -85
  103. package/lib/WAUSync/USyncUser.js +23 -25
  104. package/lib/WAUSync/index.js +5 -19
  105. package/lib/index.js +19 -34
  106. package/package.json +89 -106
  107. package/engine-requirements.js +0 -10
  108. package/lib/Defaults/baileys-version.json +0 -3
  109. package/lib/Defaults/index.d.ts +0 -53
  110. package/lib/Defaults/phonenumber-mcc.json +0 -223
  111. package/lib/Signal/Group/ciphertext-message.d.ts +0 -9
  112. package/lib/Signal/Group/group-session-builder.d.ts +0 -14
  113. package/lib/Signal/Group/group_cipher.d.ts +0 -17
  114. package/lib/Signal/Group/index.d.ts +0 -11
  115. package/lib/Signal/Group/keyhelper.d.ts +0 -10
  116. package/lib/Signal/Group/queue-job.d.ts +0 -1
  117. package/lib/Signal/Group/queue-job.js +0 -57
  118. package/lib/Signal/Group/sender-chain-key.d.ts +0 -13
  119. package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -16
  120. package/lib/Signal/Group/sender-key-message.d.ts +0 -18
  121. package/lib/Signal/Group/sender-key-name.d.ts +0 -17
  122. package/lib/Signal/Group/sender-key-record.d.ts +0 -30
  123. package/lib/Signal/Group/sender-key-state.d.ts +0 -38
  124. package/lib/Signal/Group/sender-message-key.d.ts +0 -11
  125. package/lib/Signal/libsignal.d.ts +0 -3
  126. package/lib/Socket/Client/abstract-socket-client.d.ts +0 -17
  127. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  128. package/lib/Socket/Client/index.d.ts +0 -3
  129. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  130. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  131. package/lib/Socket/Client/web-socket-client.d.ts +0 -12
  132. package/lib/Socket/Client/web-socket-client.js +0 -62
  133. package/lib/Socket/business.d.ts +0 -171
  134. package/lib/Socket/chats.d.ts +0 -267
  135. package/lib/Socket/chats.js.bak +0 -981
  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,69 +1,89 @@
1
-
2
- "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.makeMessagesSocket = void 0;
8
- const boom_1 = require("@hapi/boom");
9
- const node_cache_1 = __importDefault(require("node-cache"));
10
- const WAProto_1 = require("../../WAProto");
11
- const Defaults_1 = require("../Defaults");
12
- const axios_1 = require("axios")
13
- const Types_1 = require("../Types")
14
- const Utils_1 = require("../Utils");
15
- const link_preview_1 = require("../Utils/link-preview");
16
- const WABinary_1 = require("../WABinary");
17
- const newsletter_1 = require("./newsletter");
18
- const WAUSync_1 = require("../WAUSync")
19
- const kikyy = require('./dugong');
20
- var ListType = WAProto_1.proto.Message.ListMessage.ListType;
21
- const makeMessagesSocket = (config) => {
22
- const {
23
- logger,
24
- linkPreviewImageThumbnailWidth,
25
- generateHighQualityLinkPreview,
26
- options: axiosOptions,
27
- patchMessageBeforeSending
28
- } = config;
29
- const sock = (0, newsletter_1.makeNewsletterSocket)(config);
30
- const {
31
- ev,
32
- authState,
33
- processingMutex,
34
- signalRepository,
35
- upsertMessage,
36
- query,
37
- fetchPrivacySettings,
38
- generateMessageTag,
39
- sendNode,
40
- groupMetadata,
41
- groupToggleEphemeral,
42
- executeUSyncQuery
43
- } = sock;
44
- const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
45
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
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,
46
61
  useClones: false
47
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();
48
67
  let mediaConn;
49
68
  const refreshMediaConn = async (forceGet = false) => {
50
69
  const media = await mediaConn;
51
- 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) {
52
71
  mediaConn = (async () => {
53
72
  const result = await query({
54
73
  tag: 'iq',
55
74
  attrs: {
56
75
  type: 'set',
57
76
  xmlns: 'w:m',
58
- to: WABinary_1.S_WHATSAPP_NET,
77
+ to: S_WHATSAPP_NET
59
78
  },
60
79
  content: [{ tag: 'media_conn', attrs: {} }]
61
80
  });
62
- 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
63
83
  const node = {
64
- hosts: WABinary_1.getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
84
+ hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
65
85
  hostname: attrs.hostname,
66
- maxContentLengthBytes: +attrs.maxContentLengthBytes,
86
+ maxContentLengthBytes: +attrs.maxContentLengthBytes
67
87
  })),
68
88
  auth: mediaConnNode.attrs.auth,
69
89
  ttl: +mediaConnNode.attrs.ttl,
@@ -80,17 +100,20 @@ const makeMessagesSocket = (config) => {
80
100
  * used for receipts of phone call, read, delivery etc.
81
101
  * */
82
102
  const sendReceipt = async (jid, participant, messageIds, type) => {
103
+ if (!messageIds || messageIds.length === 0) {
104
+ throw new Boom('missing ids in receipt');
105
+ }
83
106
  const node = {
84
107
  tag: 'receipt',
85
108
  attrs: {
86
- id: messageIds[0],
87
- },
109
+ id: messageIds[0]
110
+ }
88
111
  };
89
112
  const isReadReceipt = type === 'read' || type === 'read-self';
90
113
  if (isReadReceipt) {
91
- node.attrs.t = (0, Utils_1.unixTimestampSeconds)().toString();
114
+ node.attrs.t = unixTimestampSeconds().toString();
92
115
  }
93
- if (type === 'sender' && WABinary_1.isJidUser(jid)) {
116
+ if (type === 'sender' && (isPnUser(jid) || isLidUser(jid))) {
94
117
  node.attrs.recipient = jid;
95
118
  node.attrs.to = participant;
96
119
  }
@@ -101,7 +124,7 @@ const makeMessagesSocket = (config) => {
101
124
  }
102
125
  }
103
126
  if (type) {
104
- node.attrs.type = WABinary_1.isJidNewsLetter(jid) ? 'read-self' : type;
127
+ node.attrs.type = type;
105
128
  }
106
129
  const remainingMessageIds = messageIds.slice(1);
107
130
  if (remainingMessageIds.length) {
@@ -121,7 +144,7 @@ const makeMessagesSocket = (config) => {
121
144
  };
122
145
  /** Correctly bulk send receipts to multiple chats, participants */
123
146
  const sendReceipts = async (keys, type) => {
124
- const recps = (0, Utils_1.aggregateMessageKeysNotFromMe)(keys);
147
+ const recps = aggregateMessageKeysNotFromMe(keys);
125
148
  for (const { jid, participant, messageIds } of recps) {
126
149
  await sendReceipt(jid, participant, messageIds, type);
127
150
  }
@@ -135,207 +158,349 @@ const makeMessagesSocket = (config) => {
135
158
  };
136
159
  /** Fetch all the devices we've to send a message to */
137
160
  const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
138
- const deviceResults = []
139
-
161
+ const deviceResults = [];
140
162
  if (!useCache) {
141
- logger.debug('not using cache for devices')
163
+ logger.debug('not using cache for devices');
142
164
  }
143
-
144
- const toFetch = []
145
-
146
- jids = Array.from(new Set(jids))
147
-
148
- for (let jid of jids) {
149
- const user = WABinary_1.jidDecode(jid)?.user
150
-
151
- jid = WABinary_1.jidNormalizedUser(jid)
152
-
165
+ 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) {
153
190
  if (useCache) {
154
- const devices = userDevicesCache.get(user)
155
-
191
+ const devices = mgetDevices?.[user] ||
192
+ (userDevicesCache.mget ? undefined : (await userDevicesCache.get(user)));
156
193
  if (devices) {
157
- deviceResults.push(...devices)
158
- 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');
159
200
  }
160
-
161
201
  else {
162
- toFetch.push(jid)
202
+ toFetch.push(jid);
163
203
  }
164
204
  }
165
-
166
205
  else {
167
- toFetch.push(jid)
206
+ toFetch.push(jid);
168
207
  }
169
208
  }
170
-
171
209
  if (!toFetch.length) {
172
- return deviceResults
210
+ return deviceResults;
173
211
  }
174
-
175
- const query = new WAUSync_1.USyncQuery()
176
- .withContext('message')
177
- .withDeviceProtocol()
178
-
212
+ const requestedLidUsers = new Set();
179
213
  for (const jid of toFetch) {
180
- 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
+ }
181
219
  }
182
-
183
- const result = await executeUSyncQuery(query)
184
-
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);
185
225
  if (result) {
186
- const extracted = Utils_1.extractDeviceJids(result?.list, authState.creds.me.id, ignoreZeroDevices)
187
- const deviceMap = {}
188
-
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 = {};
189
234
  for (const item of extracted) {
190
- deviceMap[item.user] = deviceMap[item.user] || []
191
- deviceMap[item.user].push(item)
192
- deviceResults.push(item)
235
+ deviceMap[item.user] = deviceMap[item.user] || [];
236
+ deviceMap[item.user]?.push(item);
193
237
  }
194
-
195
- for (const key in deviceMap) {
196
- 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
+ }
197
282
  }
198
283
  }
199
-
200
- return deviceResults
201
- }
202
- const assertSessions = async (jids, force) => {
284
+ return deviceResults;
285
+ };
286
+ const assertSessions = async (jids) => {
203
287
  let didFetchNewSession = false;
204
- let jidsRequiringFetch = [];
205
- if (force) {
206
- jidsRequiringFetch = jids;
207
- }
208
- else {
209
- const addrs = jids.map(jid => (signalRepository
210
- .jidToSignalProtocolAddress(jid)));
211
- const sessions = await authState.keys.get('session', addrs);
212
- for (const jid of jids) {
213
- const signalId = signalRepository
214
- .jidToSignalProtocolAddress(jid);
215
- if (!sessions[signalId]) {
216
- jidsRequiringFetch.push(jid);
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
217
298
  }
218
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;
306
+ }
307
+ }
308
+ jidsRequiringFetch.push(jid);
219
309
  }
220
310
  if (jidsRequiringFetch.length) {
221
- 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');
222
317
  const result = await query({
223
318
  tag: 'iq',
224
319
  attrs: {
225
320
  xmlns: 'encrypt',
226
321
  type: 'get',
227
- to: WABinary_1.S_WHATSAPP_NET,
322
+ to: S_WHATSAPP_NET
228
323
  },
229
324
  content: [
230
325
  {
231
326
  tag: 'key',
232
327
  attrs: {},
233
- content: jidsRequiringFetch.map(jid => ({
328
+ content: wireJids.map(jid => ({
234
329
  tag: 'user',
235
- attrs: { jid },
330
+ attrs: { jid }
236
331
  }))
237
332
  }
238
333
  ]
239
334
  });
240
- await (0, Utils_1.parseAndInjectE2ESessions)(result, signalRepository);
335
+ await parseAndInjectE2ESessions(result, signalRepository);
241
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
+ }
242
342
  }
243
343
  return didFetchNewSession;
244
344
  };
245
-
246
-
247
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
248
347
  if (!authState.creds.me?.id) {
249
- throw new boom_1.Boom('Not authenticated')
348
+ throw new Boom('Not authenticated');
250
349
  }
251
-
252
350
  const protocolMessage = {
253
351
  protocolMessage: {
254
352
  peerDataOperationRequestMessage: pdoMessage,
255
- type: WAProto_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
353
+ type: proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
256
354
  }
257
355
  };
258
- const meJid = WABinary_1.jidNormalizedUser(authState.creds.me.id);
356
+ const meJid = jidNormalizedUser(authState.creds.me.id);
259
357
  const msgId = await relayMessage(meJid, protocolMessage, {
260
358
  additionalAttributes: {
261
359
  category: 'peer',
262
- // eslint-disable-next-line camelcase
263
- push_priority: 'high_force',
360
+ push_priority: 'high_force'
264
361
  },
362
+ additionalNodes: [
363
+ {
364
+ tag: 'meta',
365
+ attrs: { appdata: 'default' }
366
+ }
367
+ ]
265
368
  });
266
369
  return msgId;
267
370
  };
268
- const createParticipantNodes = async (jids, message, extraAttrs) => {
269
- const patched = await patchMessageBeforeSending(message, jids);
270
- 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 }));
271
379
  let shouldIncludeDeviceIdentity = false;
272
- const nodes = await Promise.all(jids.map(async (jid) => {
273
- const { type, ciphertext } = await signalRepository
274
- .encryptMessage({ jid, data: bytes });
275
- if (type === 'pkmsg') {
276
- shouldIncludeDeviceIdentity = true;
277
- }
278
- const node = {
279
- tag: 'to',
280
- attrs: { jid },
281
- content: [{
282
- tag: 'enc',
283
- attrs: {
284
- v: '2',
285
- type,
286
- ...extraAttrs || {}
287
- },
288
- content: ciphertext
289
- }]
290
- };
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
+ });
291
424
  return node;
292
- }));
425
+ });
426
+ const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
293
427
  return { nodes, shouldIncludeDeviceIdentity };
294
- }; //apela
295
- const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, cachedGroupMetadata, useCachedGroupMetadata, statusJidList, AI = false }) => {
296
- const meId = authState.creds.me.id;
297
- let shouldIncludeDeviceIdentity = false;
428
+ };
429
+ const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, AI = false }) => {
430
+ // let shouldIncludeDeviceIdentity = false;
298
431
  let didPushAdditional = false
299
- 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;
300
436
  const statusJid = 'status@broadcast';
437
+ const { user, server } = jidDecode(jid);
301
438
  const isGroup = server === 'g.us';
302
439
  const isStatus = jid === statusJid;
303
440
  const isLid = server === 'lid';
304
- const isPrivate = server === 's.whatsapp.net'
305
441
  const isNewsletter = server === 'newsletter';
306
- msgId = msgId || (0, Utils_1.generateMessageID)();
442
+ const isPrivate = server === 's.whatsapp.net'
443
+ const finalJid = jid;
444
+ msgId = msgId || generateMessageIDV2(meId);
307
445
  useUserDevicesCache = useUserDevicesCache !== false;
308
- useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
446
+ useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
309
447
  const participants = [];
310
- const destinationJid = (!isStatus) ? WABinary_1.jidEncode(user, isLid ? 'lid' : isGroup ? 'g.us' : isNewsletter ? 'newsletter' : 's.whatsapp.net') : statusJid;
448
+ const destinationJid = !isStatus ? finalJid : statusJid;
311
449
  const binaryNodeContent = [];
312
450
  const devices = [];
313
451
  const meMsg = {
314
452
  deviceSentMessage: {
315
453
  destinationJid,
316
454
  message
317
- }
455
+ },
456
+ messageContextInfo: message.messageContextInfo
318
457
  };
319
- const extraAttrs = {}
320
- const messages = Utils_1.normalizeMessageContent(message)
458
+ const extraAttrs = {};
459
+ const messages = normalizeMessageContent(message)
321
460
  const buttonType = getButtonType(messages);
322
461
  if (participant) {
323
- // when the retry request is not for a group
324
- // only send to the specific device that asked for a retry
325
- // otherwise the message is sent out to every device that should be a recipient
326
462
  if (!isGroup && !isStatus) {
327
- additionalAttributes = { ...additionalAttributes, 'device_fanout': 'false' };
463
+ additionalAttributes = {
464
+ ...additionalAttributes,
465
+ device_fanout: 'false'
466
+ };
328
467
  }
329
- const { user, device } = WABinary_1.jidDecode(participant.jid);
330
- devices.push({ user, device });
468
+ const { user, device } = jidDecode(participant.jid);
469
+ devices.push({
470
+ user,
471
+ device,
472
+ jid: participant.jid
473
+ });
331
474
  }
332
475
  await authState.keys.transaction(async () => {
333
- const mediaType = getMediaType(messages);
334
-
476
+ const mediaType = getMediaType(message);
335
477
  if (mediaType) {
336
- extraAttrs['mediatype'] = mediaType
478
+ extraAttrs['mediatype'] = mediaType;
337
479
  }
338
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
+
339
504
  if (messages.pinInChatMessage || messages.keepInChatMessage || message.reactionMessage || message.protocolMessage?.editedMessage) {
340
505
  extraAttrs['decrypt-fail'] = 'hide'
341
506
  }
@@ -347,185 +512,228 @@ const makeMessagesSocket = (config) => {
347
512
  if (isGroup || isStatus) {
348
513
  const [groupData, senderKeyMap] = await Promise.all([
349
514
  (async () => {
350
- let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined
351
- if (groupData) {
352
- 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');
353
521
  }
354
-
355
522
  else if (!isStatus) {
356
- groupData = await groupMetadata(jid)
523
+ groupData = await groupMetadata(jid); // TODO: start storing group participant list + addr mode in Signal & stop relying on this
357
524
  }
358
-
359
525
  return groupData;
360
526
  })(),
361
527
  (async () => {
362
528
  if (!participant && !isStatus) {
363
- const result = await authState.keys.get('sender-key-memory', [jid])
364
- 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] || {};
365
533
  }
366
-
367
- return {}
368
-
369
- })()
534
+ return {};
535
+ })()
370
536
  ]);
371
537
  if (!participant) {
372
- const participantsList = (groupData && !isStatus) ? groupData.participants.map(p => p.id) : []
373
-
538
+ const participantsList = groupData && !isStatus ? groupData.participants.map(p => p.id) : [];
374
539
  if (isStatus && statusJidList) {
375
- participantsList.push(...statusJidList)
540
+ participantsList.push(...statusJidList);
376
541
  }
377
-
378
- // if (!isStatus) {
379
- // const expiration = await getEphemeralGroup(jid)
380
- // additionalAttributes = {
381
- // ...additionalAttributes,
382
- // addressing_mode: 'pn',
383
- // ...expiration ? { expiration: expiration.toString() } : null
384
- // }
385
- // }
386
-
387
- const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false)
388
- 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);
550
+ }
551
+ if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
552
+ additionalAttributes = {
553
+ ...additionalAttributes,
554
+ expiration: groupData.ephemeralDuration.toString()
555
+ };
389
556
  }
390
-
391
- const patched = await patchMessageBeforeSending(message, devices.map(d => WABinary_1.jidEncode(d.user, isLid ? 'lid' : 's.whatsapp.net', d.device)));
392
- const bytes = Utils_1.encodeWAMessage(patched);
393
-
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;
394
564
  const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
395
565
  group: destinationJid,
396
566
  data: bytes,
397
- meId,
567
+ meId: groupSenderIdentity
398
568
  });
399
- const senderKeyJids = [];
400
-
401
- for (const { user, device } of devices) {
402
- const jid = WABinary_1.jidEncode(user, (groupData === null || groupData === void 0 ? void 0 : groupData.addressingMode) === 'lid' ? 'lid' : 's.whatsapp.net', device);
403
- if (!senderKeyMap[jid] || !!participant) {
404
- senderKeyJids.push(jid);
405
- // store that this person has had the sender keys sent to them
406
- 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;
407
581
  }
408
582
  }
409
- // if there are some participants with whom the session has not been established
410
- // if there are, we re-send the senderkey
411
- if (senderKeyJids.length) {
412
- logger.debug({ senderKeyJids }, 'sending new sender key');
583
+ if (senderKeyRecipients.length) {
584
+ logger.debug({ senderKeyJids: senderKeyRecipients }, 'sending new sender key');
413
585
  const senderKeyMsg = {
414
586
  senderKeyDistributionMessage: {
415
587
  axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
416
588
  groupId: destinationJid
417
589
  }
418
590
  };
419
- await assertSessions(senderKeyJids, false);
420
- const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, extraAttrs)
591
+ const senderKeySessionTargets = senderKeyRecipients;
592
+ await assertSessions(senderKeySessionTargets);
593
+ const result = await createParticipantNodes(senderKeyRecipients, senderKeyMsg, extraAttrs);
421
594
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
422
595
  participants.push(...result.nodes);
423
596
  }
424
- binaryNodeContent.push({
425
- tag: 'enc',
426
- attrs: { v: '2', type: 'skmsg', ...extraAttrs },
427
- content: ciphertext
428
- });
429
- await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
430
- }
431
- else if (isNewsletter) {
432
- // Message edit
433
- if (message.protocolMessage?.editedMessage) {
434
- msgId = message.protocolMessage.key?.id
435
- 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
+ });
436
611
  }
437
-
438
- // Message delete
439
- if (message.protocolMessage?.type === WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE) {
440
- msgId = message.protocolMessage.key?.id
441
- 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 } });
442
623
  }
443
-
444
- const patched = await patchMessageBeforeSending(message, [])
445
- const bytes = Utils_1.encodeNewsletterMessage(patched)
446
-
447
- binaryNodeContent.push({
448
- tag: 'plaintext',
449
- attrs: extraAttrs ? extraAttrs : {},
450
- content: bytes
451
- })
452
624
  }
453
625
  else {
454
- 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);
455
637
  if (!participant) {
456
- devices.push({ user })
457
- if (user !== meUser) {
458
- 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
+ });
459
652
  }
460
-
461
653
  if (additionalAttributes?.['category'] !== 'peer') {
462
- const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true)
463
-
464
- 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');
465
667
  }
466
668
  }
467
- const allJids = [];
468
- const meJids = [];
469
- const otherJids = [];
470
- for (const { user, device } of devices) {
471
- const isMe = user === meUser
472
- const jid = WABinary_1.jidEncode(isMe && isLid ? authState.creds?.me?.lid?.split(':')[0] || user : user, isLid ? 'lid' : 's.whatsapp.net', device)
473
-
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;
474
682
  if (isMe) {
475
- meJids.push(jid)
683
+ meRecipients.push(jid);
476
684
  }
477
-
478
685
  else {
479
- otherJids.push(jid)
686
+ otherRecipients.push(jid);
480
687
  }
481
-
482
- allJids.push(jid)
688
+ allRecipients.push(jid);
483
689
  }
484
- await assertSessions(allJids, false);
690
+ await assertSessions(allRecipients);
485
691
  const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
486
- createParticipantNodes(meJids, meMsg, extraAttrs),
487
- createParticipantNodes(otherJids, message, extraAttrs)
488
- ])
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
+ ]);
489
696
  participants.push(...meNodes);
490
697
  participants.push(...otherNodes);
698
+ /* if (meRecipients.length > 0 || otherRecipients.length > 0) {
699
+ extraAttrs['phash'] = generateParticipantHashV2([...meRecipients, ...otherRecipients]);
700
+ }*/
491
701
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
492
702
  }
493
703
  if (participants.length) {
494
704
  if (additionalAttributes?.['category'] === 'peer') {
495
- const peerNode = participants[0]?.content?.[0]
496
-
705
+ const peerNode = participants[0]?.content?.[0];
497
706
  if (peerNode) {
498
- binaryNodeContent.push(peerNode) // push only enc
707
+ binaryNodeContent.push(peerNode); // push only enc
499
708
  }
500
709
  }
501
-
502
710
  else {
503
711
  binaryNodeContent.push({
504
712
  tag: 'participants',
505
713
  attrs: {},
506
714
  content: participants
507
- })
715
+ });
508
716
  }
509
717
  }
510
-
511
718
  const stanza = {
512
719
  tag: 'message',
513
720
  attrs: {
514
721
  id: msgId,
515
- type: getTypeMessage(messages),
722
+ to: destinationJid,
723
+ type: getTypeMessage(messages),
516
724
  ...(additionalAttributes || {})
517
725
  },
518
726
  content: binaryNodeContent
519
- }
727
+ };
520
728
  // if the participant to send to is explicitly specified (generally retry recp)
521
729
  // ensure the message is only sent to that person
522
730
  // if a retry receipt is sent to everyone -- it'll fail decryption for everyone else who received the msg
523
731
  if (participant) {
524
- if (WABinary_1.isJidGroup(destinationJid)) {
732
+ if (isJidGroup(destinationJid)) {
525
733
  stanza.attrs.to = destinationJid;
526
734
  stanza.attrs.participant = participant.jid;
527
735
  }
528
- else if (WABinary_1.areJidsSameUser(participant.jid, meId)) {
736
+ else if (areJidsSameUser(participant.jid, meId)) {
529
737
  stanza.attrs.to = participant.jid;
530
738
  stanza.attrs.recipient = destinationJid;
531
739
  }
@@ -537,14 +745,14 @@ const makeMessagesSocket = (config) => {
537
745
  stanza.attrs.to = destinationJid;
538
746
  }
539
747
  if (shouldIncludeDeviceIdentity) {
748
+ ;
540
749
  stanza.content.push({
541
750
  tag: 'device-identity',
542
751
  attrs: {},
543
- content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
752
+ content: encodeSignedDeviceIdentity(authState.creds.account, true)
544
753
  });
545
754
  logger.debug({ jid }, 'adding device identity');
546
755
  }
547
-
548
756
  if (AI && isPrivate) {
549
757
  const botNode = {
550
758
  tag: 'bot',
@@ -553,7 +761,7 @@ const makeMessagesSocket = (config) => {
553
761
  }
554
762
  }
555
763
 
556
- const filteredBizBot = WABinary_1.getBinaryNodeFilter(additionalNodes ? additionalNodes : [])
764
+ const filteredBizBot = getBinaryNodeFilter(additionalNodes ? additionalNodes : [])
557
765
 
558
766
  if (filteredBizBot) {
559
767
  stanza.content.push(...additionalNodes)
@@ -565,9 +773,9 @@ const makeMessagesSocket = (config) => {
565
773
  }
566
774
  }
567
775
 
568
- if(!isNewsletter && buttonType && !isStatus) {
569
- const content = WABinary_1.getAdditionalNode(buttonType)
570
- const filteredNode = WABinary_1.getBinaryNodeFilter(additionalNodes)
776
+ if(buttonType && !isStatus) {
777
+ const content = getAdditionalNode(buttonType)
778
+ const filteredNode = getBinaryNodeFilter(additionalNodes)
571
779
 
572
780
  if (filteredNode) {
573
781
  didPushAdditional = true
@@ -582,42 +790,44 @@ const makeMessagesSocket = (config) => {
582
790
  if (!didPushAdditional && additionalNodes && additionalNodes.length > 0) {
583
791
  stanza.content.push(...additionalNodes);
584
792
  }
585
-
586
793
  logger.debug({ msgId }, `sending message to ${participants.length} devices`);
587
794
  await sendNode(stanza);
588
- });
589
-
590
- message = Types_1.WAProto.Message.fromObject(message)
591
-
592
- const messageJSON = {
593
- key: {
594
- remoteJid: jid,
595
- fromMe: true,
596
- id: msgId
597
- },
598
- message: message,
599
- messageTimestamp: Utils_1.unixTimestampSeconds(new Date()),
600
- messageStubParameters: [],
601
- participant: WABinary_1.isJidGroup(jid) || WABinary_1.isJidStatusBroadcast(jid) ? meId : undefined,
602
- status: Types_1.WAMessageStatus.PENDING
603
- }
604
-
605
- return Types_1.WAProto.WebMessageInfo.fromObject(messageJSON)
606
- // 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;
607
801
  };
608
802
  const getTypeMessage = (msg) => {
609
- const message = Utils_1.normalizeMessageContent(msg)
610
- if (message.reactionMessage) {
611
- return 'reaction'
612
- }
613
- else if (getMediaType(message)) {
614
- return 'media'
615
- }
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
+ }
616
827
  else {
617
- return 'text'
828
+ return 'text';
618
829
  }
619
- }
620
-
830
+ };
621
831
  const getMediaType = (message) => {
622
832
  if (message.imageMessage) {
623
833
  return 'image'
@@ -667,8 +877,7 @@ const makeMessagesSocket = (config) => {
667
877
  else if (/https:\/\/wa\.me\/p\/\d+\/\d+/.test(message.extendedTextMessage?.text)) {
668
878
  return 'productlink'
669
879
  }
670
- }
671
-
880
+ }
672
881
  const getButtonType = (message) => {
673
882
  if (message.listMessage) {
674
883
  return 'list'
@@ -699,11 +908,11 @@ const makeMessagesSocket = (config) => {
699
908
  }
700
909
  }
701
910
  const getPrivacyTokens = async (jids) => {
702
- const t = Utils_1.unixTimestampSeconds().toString();
911
+ const t = unixTimestampSeconds().toString();
703
912
  const result = await query({
704
913
  tag: 'iq',
705
914
  attrs: {
706
- to: WABinary_1.S_WHATSAPP_NET,
915
+ to: S_WHATSAPP_NET,
707
916
  type: 'set',
708
917
  xmlns: 'privacy'
709
918
  },
@@ -714,7 +923,7 @@ const makeMessagesSocket = (config) => {
714
923
  content: jids.map(jid => ({
715
924
  tag: 'token',
716
925
  attrs: {
717
- jid: WABinary_1.jidNormalizedUser(jid),
926
+ jid: jidNormalizedUser(jid),
718
927
  t,
719
928
  type: 'trusted_contact'
720
929
  }
@@ -723,10 +932,9 @@ const makeMessagesSocket = (config) => {
723
932
  ]
724
933
  });
725
934
  return result;
726
- }
727
- const waUploadToServer = (0, Utils_1.getWAUploadToServer)(config, refreshMediaConn);
728
- const rahmi = new kikyy(Utils_1, waUploadToServer, relayMessage);
729
- 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');
730
938
  return {
731
939
  ...sock,
732
940
  getPrivacyTokens,
@@ -734,23 +942,23 @@ const makeMessagesSocket = (config) => {
734
942
  relayMessage,
735
943
  sendReceipt,
736
944
  sendReceipts,
737
- rahmi,
738
945
  readMessages,
739
946
  refreshMediaConn,
740
- getUSyncDevices,
741
- createParticipantNodes,
742
947
  waUploadToServer,
743
- sendPeerDataOperationMessage,
744
948
  fetchPrivacySettings,
949
+ sendPeerDataOperationMessage,
950
+ createParticipantNodes,
951
+ getUSyncDevices,
952
+ messageRetryManager,
745
953
  updateMediaMessage: async (message) => {
746
- const content = (0, Utils_1.assertMediaContent)(message.message);
954
+ const content = assertMediaContent(message.message);
747
955
  const mediaKey = content.mediaKey;
748
956
  const meId = authState.creds.me.id;
749
- const node = (0, Utils_1.encryptMediaRetryRequest)(message.key, mediaKey, meId);
957
+ const node = await encryptMediaRetryRequest(message.key, mediaKey, meId);
750
958
  let error = undefined;
751
959
  await Promise.all([
752
960
  sendNode(node),
753
- waitForMsgMediaUpdate(update => {
961
+ waitForMsgMediaUpdate(async (update) => {
754
962
  const result = update.find(c => c.key.id === message.key.id);
755
963
  if (result) {
756
964
  if (result.error) {
@@ -758,13 +966,16 @@ const makeMessagesSocket = (config) => {
758
966
  }
759
967
  else {
760
968
  try {
761
- const media = (0, Utils_1.decryptMediaRetryData)(result.media, mediaKey, result.key.id);
762
- if (media.result !== WAProto_1.proto.MediaRetryNotification.ResultType.SUCCESS) {
763
- const resultStr = WAProto_1.proto.MediaRetryNotification.ResultType[media.result];
764
- 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
+ });
765
976
  }
766
977
  content.directPath = media.directPath;
767
- content.url = (0, Utils_1.getUrlFromDirectPath)(content.directPath);
978
+ content.url = getUrlFromDirectPath(content.directPath);
768
979
  logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful');
769
980
  }
770
981
  catch (err) {
@@ -778,133 +989,112 @@ const makeMessagesSocket = (config) => {
778
989
  if (error) {
779
990
  throw error;
780
991
  }
781
- ev.emit('messages.update', [
782
- {
783
- key: message.key,
784
- update: {
785
- message: message.message
786
- }
787
- }
788
- ]);
992
+ ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
789
993
  return message;
790
994
  },
791
995
  sendMessage: async (jid, content, options = {}) => {
792
996
  const userJid = authState.creds.me.id;
793
- delete options.ephemeralExpiration
794
- const { filter = false, quoted } = options;
795
- const getParticipantAttr = () => filter ? { participant: { jid } } : {};
796
- const messageType = rahmi.detectType(content);
797
- if (typeof content === 'object' && 'disappearingMessagesInChat' in content &&
798
- typeof content['disappearingMessagesInChat'] !== 'undefined' && WABinary_1.isJidGroup(jid)) {
799
- const { disappearingMessagesInChat } = content
800
-
801
- const value = typeof disappearingMessagesInChat === 'boolean' ?
802
- (disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
803
- disappearingMessagesInChat
804
-
805
- 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);
806
1008
  }
807
-
808
1009
  else {
809
- let mediaHandle
810
-
811
-
812
- if (messageType) {
813
- switch(messageType) {
814
- case 'PAYMENT':
815
- const paymentContent = await rahmi.handlePayment(content, quoted);
816
- return await relayMessage(jid, paymentContent, {
817
- messageId: Utils_1.generateMessageID(),
818
- ...getParticipantAttr()
819
- });
820
-
821
- case 'PRODUCT':
822
- const productContent = await rahmi.handleProduct(content, jid, quoted);
823
- const productMsg = await Utils_1.generateWAMessageFromContent(jid, productContent, { quoted });
824
- return await relayMessage(jid, productMsg.message, {
825
- messageId: productMsg.key.id,
826
- ...getParticipantAttr()
827
- });
828
-
829
- case 'INTERACTIVE':
830
- const interactiveContent = await rahmi.handleInteractive(content, jid, quoted);
831
- const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted });
832
- return await relayMessage(jid, interactiveMsg.message, {
833
- messageId: interactiveMsg.key.id,
834
- ...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)
835
1029
  });
836
- case 'ALBUM':
837
- return await rahmi.handleAlbum(content, jid, quoted)
838
- case 'EVENT':
839
- return await rahmi.handleEvent(content, jid, quoted)
840
- case 'POLL_RESULT':
841
- return await rahmi.handlePollResult(content, jid, quoted)
842
- case 'GROUP_STORY':
843
- return await rahmi.handleGroupStory(content, jid, quoted)
844
- }
845
- }
846
- const fullMsg = await Utils_1.generateWAMessage(jid, content, {
847
- logger,
848
- userJid,
849
- quoted,
850
- getUrlInfo: text => link_preview_1.getUrlInfo(text, {
851
- thumbnailWidth: linkPreviewImageThumbnailWidth,
852
- fetchOpts: {
853
- timeout: 3000,
854
- ...axiosOptions || {}
1030
+ return up;
855
1031
  },
856
- logger,
857
- uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
858
- }),
859
- upload: async (readStream, opts) => {
860
- const up = await waUploadToServer(readStream, {
861
- ...opts,
862
- newsletter: WABinary_1.isJidNewsLetter(jid)
863
- });
864
- return up;
865
- },
866
- mediaCache: config.mediaCache,
867
- options: config.options,
868
- ...options
869
- });
870
-
871
- const isDeleteMsg = 'delete' in content && !!content.delete;
872
- const isEditMsg = 'edit' in content && !!content.edit;
873
- const isAiMsg = 'ai' in content && !!content.ai;
874
-
875
- const additionalAttributes = {};
876
- const additionalNodes = [];
877
-
878
- if (isDeleteMsg) {
879
- const fromMe = content.delete?.fromMe;
880
- const isGroup = WABinary_1.isJidGroup(content.delete?.remoteJid);
881
- additionalAttributes.edit = (isGroup && !fromMe) || WABinary_1.isJidNewsLetter(jid) ? '8' : '7';
882
- } else if (isEditMsg) {
883
- additionalAttributes.edit = WABinary_1.isJidNewsLetter(jid) ? '3' : '1';
884
- } else if (isAiMsg) {
885
- 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({
886
1060
  attrs: {
887
1061
  biz_bot: '1'
888
1062
  }, tag: "bot"
889
1063
  });
890
- }
891
-
892
- await relayMessage(jid, fullMsg.message, {
893
- messageId: fullMsg.key.id,
894
- cachedGroupMetadata: options.cachedGroupMetadata,
895
- additionalNodes: isAiMsg ? additionalNodes : options.additionalNodes,
896
- additionalAttributes,
897
- statusJidList: options.statusJidList
898
- });
899
-
900
- if (config.emitOwnEvents) {
901
- process.nextTick(() => {
902
- 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
903
1090
  });
904
- }
905
- return fullMsg;
1091
+ if (config.emitOwnEvents) {
1092
+ process.nextTick(() => {
1093
+ processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1094
+ });
1095
+ }
1096
+ return fullMsg;
906
1097
  }
907
1098
  }
908
- }
909
- };
910
- exports.makeMessagesSocket = makeMessagesSocket;
1099
+ };
1100
+ };