cuki-bailx 1.2.4 → 1.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/LICENSE +21 -0
  2. package/WAProto/GenerateStatics.sh +4 -0
  3. package/WAProto/WAProto.proto +4775 -0
  4. package/WAProto/index.js +56886 -17506
  5. package/engine-requirements.js +1 -1
  6. package/lib/Defaults/index.js +98 -108
  7. package/lib/Defaults/vyzen-baileysx-version.json +3 -0
  8. package/lib/Signal/libsignal.js +2 -0
  9. package/lib/Socket/Client/index.js +2 -3
  10. package/lib/Socket/Client/{web-socket-client.js → websocket.js} +54 -5
  11. package/lib/Socket/chats.js +224 -173
  12. package/lib/Socket/groups.js +20 -5
  13. package/lib/Socket/index.js +2 -2
  14. package/lib/Socket/messages-recv.js +10 -66
  15. package/lib/Socket/messages-send.js +379 -312
  16. package/lib/Socket/newsletter.js +54 -40
  17. package/lib/Socket/socket.js +58 -32
  18. package/lib/Store/index.js +1 -3
  19. package/lib/Store/make-in-memory-store.js +27 -15
  20. package/lib/Store/make-ordered-dictionary.js +2 -2
  21. package/lib/Types/Label.js +1 -1
  22. package/lib/Types/LabelAssociation.js +1 -1
  23. package/lib/Types/Message.js +0 -2
  24. package/lib/Types/Newsletter.js +3 -17
  25. package/lib/Types/index.js +2 -2
  26. package/lib/Utils/auth-utils.js +6 -13
  27. package/lib/Utils/baileys-event-stream.js +1 -1
  28. package/lib/Utils/browser-utils.js +35 -0
  29. package/lib/Utils/business.js +2 -2
  30. package/lib/Utils/chat-utils.js +36 -35
  31. package/lib/Utils/crypto.js +71 -29
  32. package/lib/Utils/decode-wa-message.js +65 -56
  33. package/lib/Utils/event-buffer.js +13 -9
  34. package/lib/Utils/generics.js +107 -29
  35. package/lib/Utils/history.js +4 -6
  36. package/lib/Utils/index.js +2 -0
  37. package/lib/Utils/link-preview.js +34 -1
  38. package/lib/Utils/lt-hash.js +6 -6
  39. package/lib/Utils/message-retry-manager.js +128 -0
  40. package/lib/Utils/messages-media.js +263 -115
  41. package/lib/Utils/messages.js +500 -93
  42. package/lib/Utils/noise-handler.js +18 -23
  43. package/lib/Utils/process-message.js +108 -25
  44. package/lib/Utils/signal.js +37 -35
  45. package/lib/Utils/use-multi-file-auth-state.js +51 -6
  46. package/lib/Utils/validate-connection.js +90 -66
  47. package/lib/WABinary/constants.js +1276 -13
  48. package/lib/WABinary/decode.js +26 -13
  49. package/lib/WABinary/encode.js +39 -17
  50. package/lib/WABinary/generic-utils.js +2 -85
  51. package/lib/WABinary/jid-utils.js +28 -5
  52. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +1 -1
  53. package/lib/index.js +18 -5
  54. package/package.json +109 -104
  55. package/lib/Defaults/baileys-version.json +0 -3
  56. package/lib/Defaults/index.d.ts +0 -53
  57. package/lib/Defaults/phonenumber-mcc.json +0 -223
  58. package/lib/Signal/Group/ciphertext-message.d.ts +0 -9
  59. package/lib/Signal/Group/group-session-builder.d.ts +0 -14
  60. package/lib/Signal/Group/group_cipher.d.ts +0 -17
  61. package/lib/Signal/Group/index.d.ts +0 -11
  62. package/lib/Signal/Group/keyhelper.d.ts +0 -10
  63. package/lib/Signal/Group/queue-job.d.ts +0 -1
  64. package/lib/Signal/Group/sender-chain-key.d.ts +0 -13
  65. package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -16
  66. package/lib/Signal/Group/sender-key-message.d.ts +0 -18
  67. package/lib/Signal/Group/sender-key-name.d.ts +0 -17
  68. package/lib/Signal/Group/sender-key-record.d.ts +0 -30
  69. package/lib/Signal/Group/sender-key-state.d.ts +0 -38
  70. package/lib/Signal/Group/sender-message-key.d.ts +0 -11
  71. package/lib/Signal/libsignal.d.ts +0 -3
  72. package/lib/Socket/Client/abstract-socket-client.d.ts +0 -17
  73. package/lib/Socket/Client/index.d.ts +0 -3
  74. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  75. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  76. package/lib/Socket/Client/web-socket-client.d.ts +0 -12
  77. package/lib/Socket/business.d.ts +0 -171
  78. package/lib/Socket/chats.d.ts +0 -80
  79. package/lib/Socket/dugong.d.ts +0 -219
  80. package/lib/Socket/dugong.js +0 -441
  81. package/lib/Socket/groups.d.ts +0 -115
  82. package/lib/Socket/index.d.ts +0 -173
  83. package/lib/Socket/messages-recv.d.ts +0 -161
  84. package/lib/Socket/messages-send.d.ts +0 -149
  85. package/lib/Socket/newsletter.d.ts +0 -134
  86. package/lib/Socket/registration.d.ts +0 -267
  87. package/lib/Socket/registration.js +0 -166
  88. package/lib/Socket/socket.d.ts +0 -43
  89. package/lib/Socket/socket.js.bak +0 -630
  90. package/lib/Socket/usync.d.ts +0 -36
  91. package/lib/Store/index.d.ts +0 -3
  92. package/lib/Store/make-cache-manager-store.d.ts +0 -13
  93. package/lib/Store/make-cache-manager-store.js +0 -83
  94. package/lib/Store/make-in-memory-store.d.ts +0 -118
  95. package/lib/Store/make-ordered-dictionary.d.ts +0 -13
  96. package/lib/Store/object-repository.d.ts +0 -10
  97. package/lib/Types/Auth.d.ts +0 -110
  98. package/lib/Types/Call.d.ts +0 -13
  99. package/lib/Types/Chat.d.ts +0 -102
  100. package/lib/Types/Contact.d.ts +0 -19
  101. package/lib/Types/Events.d.ts +0 -157
  102. package/lib/Types/GroupMetadata.d.ts +0 -55
  103. package/lib/Types/Label.d.ts +0 -35
  104. package/lib/Types/LabelAssociation.d.ts +0 -29
  105. package/lib/Types/Message.d.ts +0 -273
  106. package/lib/Types/Newsletter.d.ts +0 -92
  107. package/lib/Types/Product.d.ts +0 -78
  108. package/lib/Types/Signal.d.ts +0 -57
  109. package/lib/Types/Socket.d.ts +0 -111
  110. package/lib/Types/State.d.ts +0 -27
  111. package/lib/Types/USync.d.ts +0 -25
  112. package/lib/Types/index.d.ts +0 -57
  113. package/lib/Utils/auth-utils.d.ts +0 -18
  114. package/lib/Utils/baileys-event-stream.d.ts +0 -16
  115. package/lib/Utils/business.d.ts +0 -22
  116. package/lib/Utils/chat-utils.d.ts +0 -71
  117. package/lib/Utils/crypto.d.ts +0 -41
  118. package/lib/Utils/decode-wa-message.d.ts +0 -19
  119. package/lib/Utils/event-buffer.d.ts +0 -35
  120. package/lib/Utils/generics.d.ts +0 -92
  121. package/lib/Utils/history.d.ts +0 -15
  122. package/lib/Utils/index.d.ts +0 -17
  123. package/lib/Utils/link-preview.d.ts +0 -21
  124. package/lib/Utils/logger.d.ts +0 -4
  125. package/lib/Utils/lt-hash.d.ts +0 -12
  126. package/lib/Utils/make-mutex.d.ts +0 -7
  127. package/lib/Utils/messages-media.d.ts +0 -116
  128. package/lib/Utils/messages.d.ts +0 -77
  129. package/lib/Utils/noise-handler.d.ts +0 -21
  130. package/lib/Utils/process-message.d.ts +0 -41
  131. package/lib/Utils/signal.d.ts +0 -32
  132. package/lib/Utils/use-multi-file-auth-state.d.ts +0 -13
  133. package/lib/Utils/validate-connection.d.ts +0 -11
  134. package/lib/WABinary/constants.d.ts +0 -27
  135. package/lib/WABinary/decode.d.ts +0 -7
  136. package/lib/WABinary/encode.d.ts +0 -3
  137. package/lib/WABinary/generic-utils.d.ts +0 -16
  138. package/lib/WABinary/index.d.ts +0 -5
  139. package/lib/WABinary/jid-utils.d.ts +0 -31
  140. package/lib/WABinary/types.d.ts +0 -18
  141. package/lib/WAM/BinaryInfo.d.ts +0 -17
  142. package/lib/WAM/constants.d.ts +0 -38
  143. package/lib/WAM/encode.d.ts +0 -3
  144. package/lib/WAM/index.d.ts +0 -3
  145. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +0 -9
  146. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +0 -22
  147. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +0 -12
  148. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +0 -12
  149. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +0 -25
  150. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +0 -8
  151. package/lib/WAUSync/Protocols/index.d.ts +0 -4
  152. package/lib/WAUSync/USyncQuery.d.ts +0 -28
  153. package/lib/WAUSync/USyncUser.d.ts +0 -12
  154. package/lib/WAUSync/index.d.ts +0 -3
  155. package/lib/index.d.ts +0 -12
  156. package/lib/index.js.bak +0 -48
  157. /package/lib/Socket/Client/{abstract-socket-client.js → types.js} +0 -0
@@ -11,7 +11,7 @@ const generateIV = (counter) => {
11
11
  new DataView(iv).setUint32(8, counter);
12
12
  return new Uint8Array(iv);
13
13
  };
14
- const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey }, NOISE_HEADER, mobile, logger, routingInfo }) => {
14
+ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey }, NOISE_HEADER, logger, routingInfo }) => {
15
15
  logger = logger.child({ class: 'ns' });
16
16
  const authenticate = (data) => {
17
17
  if (!isFinished) {
@@ -38,20 +38,20 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
38
38
  authenticate(ciphertext);
39
39
  return result;
40
40
  };
41
- const localHKDF = (data) => {
42
- const key = (0, crypto_1.hkdf)(Buffer.from(data), 64, { salt, info: '' });
41
+ const localHKDF = async (data) => {
42
+ const key = await (0, crypto_1.hkdf)(Buffer.from(data), 64, { salt, info: '' });
43
43
  return [key.slice(0, 32), key.slice(32)];
44
44
  };
45
- const mixIntoKey = (data) => {
46
- const [write, read] = localHKDF(data);
45
+ const mixIntoKey = async (data) => {
46
+ const [write, read] = await localHKDF(data);
47
47
  salt = write;
48
48
  encKey = read;
49
49
  decKey = read;
50
50
  readCounter = 0;
51
51
  writeCounter = 0;
52
52
  };
53
- const finishInit = () => {
54
- const [write, read] = localHKDF(new Uint8Array(0));
53
+ const finishInit = async () => {
54
+ const [write, read] = await localHKDF(new Uint8Array(0));
55
55
  encKey = write;
56
56
  decKey = read;
57
57
  hash = Buffer.from([]);
@@ -60,7 +60,7 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
60
60
  isFinished = true;
61
61
  };
62
62
  const data = Buffer.from(Defaults_1.NOISE_MODE);
63
- let hash = Buffer.from(data.byteLength === 32 ? data : (0, crypto_1.sha256)(data));
63
+ let hash = data.byteLength === 32 ? data : (0, crypto_1.sha256)(data);
64
64
  let salt = hash;
65
65
  let encKey = hash;
66
66
  let decKey = hash;
@@ -77,24 +77,19 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
77
77
  authenticate,
78
78
  mixIntoKey,
79
79
  finishInit,
80
- processHandshake: ({ serverHello }, noiseKey) => {
80
+ processHandshake: async ({ serverHello }, noiseKey) => {
81
81
  authenticate(serverHello.ephemeral);
82
- mixIntoKey(crypto_1.Curve.sharedKey(privateKey, serverHello.ephemeral));
82
+ await mixIntoKey(crypto_1.Curve.sharedKey(privateKey, serverHello.ephemeral));
83
83
  const decStaticContent = decrypt(serverHello.static);
84
- mixIntoKey(crypto_1.Curve.sharedKey(privateKey, decStaticContent));
84
+ await mixIntoKey(crypto_1.Curve.sharedKey(privateKey, decStaticContent));
85
85
  const certDecoded = decrypt(serverHello.payload);
86
- if (mobile) {
87
- WAProto_1.proto.CertChain.NoiseCertificate.decode(certDecoded);
88
- }
89
- else {
90
- const { intermediate: certIntermediate } = WAProto_1.proto.CertChain.decode(certDecoded);
91
- const { issuerSerial } = WAProto_1.proto.CertChain.NoiseCertificate.Details.decode(certIntermediate.details);
92
- if (issuerSerial !== Defaults_1.WA_CERT_DETAILS.SERIAL) {
93
- throw new boom_1.Boom('certification match failed', { statusCode: 400 });
94
- }
86
+ const { intermediate: certIntermediate } = WAProto_1.proto.CertChain.decode(certDecoded);
87
+ const { issuerSerial } = WAProto_1.proto.CertChain.NoiseCertificate.Details.decode(certIntermediate.details);
88
+ if (issuerSerial !== Defaults_1.WA_CERT_DETAILS.SERIAL) {
89
+ throw new boom_1.Boom('certification match failed', { statusCode: 400 });
95
90
  }
96
91
  const keyEnc = encrypt(noiseKey.public);
97
- mixIntoKey(crypto_1.Curve.sharedKey(noiseKey.private, serverHello.ephemeral));
92
+ await mixIntoKey(crypto_1.Curve.sharedKey(noiseKey.private, serverHello.ephemeral));
98
93
  return keyEnc;
99
94
  },
100
95
  encodeFrame: (data) => {
@@ -125,7 +120,7 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
125
120
  frame.set(data, introSize + 3);
126
121
  return frame;
127
122
  },
128
- decodeFrame: (newData, onFrame) => {
123
+ decodeFrame: async (newData, onFrame) => {
129
124
  var _a;
130
125
  // the binary protocol uses its own framing mechanism
131
126
  // on top of the WS frames
@@ -143,7 +138,7 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
143
138
  inBytes = inBytes.slice(size + 3);
144
139
  if (isFinished) {
145
140
  const result = decrypt(frame);
146
- frame = (0, WABinary_1.decodeBinaryNode)(result);
141
+ frame = await (0, WABinary_1.decodeBinaryNode)(result);
147
142
  }
148
143
  logger.trace({ msg: (_a = frame === null || frame === void 0 ? void 0 : frame.attrs) === null || _a === void 0 ? void 0 : _a.id }, 'recv frame');
149
144
  onFrame(frame);
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.decryptPollVote = exports.getChatId = exports.shouldIncrementChatUnread = exports.isRealMessage = exports.cleanMessage = void 0;
3
+ exports.getChatId = exports.shouldIncrementChatUnread = exports.isRealMessage = exports.cleanMessage = void 0;
4
+ exports.decryptPollVote = decryptPollVote;
4
5
  const WAProto_1 = require("../../WAProto");
5
6
  const Types_1 = require("../Types");
6
7
  const messages_1 = require("../Utils/messages");
@@ -20,8 +21,21 @@ const REAL_MSG_REQ_ME_STUB_TYPES = new Set([
20
21
  /** Cleans a received message to further processing */
21
22
  const cleanMessage = (message, meId) => {
22
23
  // ensure remoteJid and participant doesn't have device or agent in it
23
- message.key.remoteJid = (0, WABinary_1.jidNormalizedUser)(message.key.remoteJid);
24
- message.key.participant = message.key.participant ? (0, WABinary_1.jidNormalizedUser)(message.key.participant) : undefined;
24
+ // normalize JIDs but catch errors to avoid throwing on invalid LIDs/JIDs
25
+ try {
26
+ message.key.remoteJid = (0, WABinary_1.jidNormalizedUser)(message.key.remoteJid);
27
+ }
28
+ catch (_e) {
29
+ // if normalization fails, retain original remoteJid
30
+ }
31
+ if (message.key.participant) {
32
+ try {
33
+ message.key.participant = (0, WABinary_1.jidNormalizedUser)(message.key.participant);
34
+ }
35
+ catch (_e) {
36
+ // ignore if can't normalize participant
37
+ }
38
+ }
25
39
  const content = (0, messages_1.normalizeMessageContent)(message.message);
26
40
  // if the message has a reaction, ensure fromMe & remoteJid are from our perspective
27
41
  if (content === null || content === void 0 ? void 0 : content.reactionMessage) {
@@ -101,14 +115,14 @@ function decryptPollVote({ encPayload, encIv }, { pollCreatorJid, pollMsgId, pol
101
115
  return Buffer.from(txt);
102
116
  }
103
117
  }
104
- exports.decryptPollVote = decryptPollVote;
105
- const processMessage = async (message, { shouldProcessHistoryMsg, ev, creds, keyStore, logger, options, getMessage }) => {
106
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
118
+ const processMessage = async (message, { shouldProcessHistoryMsg, placeholderResendCache, ev, creds, keyStore, logger, options, getMessage }) => {
119
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
107
120
  const meId = creds.me.id;
108
121
  const { accountSettings } = creds;
109
122
  const chat = { id: (0, WABinary_1.jidNormalizedUser)((0, exports.getChatId)(message.key)) };
110
123
  const isRealMsg = (0, exports.isRealMessage)(message, meId);
111
124
  if (isRealMsg) {
125
+ chat.messages = [{ message }];
112
126
  chat.conversationTimestamp = (0, generics_1.toNumber)(message.messageTimestamp);
113
127
  // only increment unread count if not CIPHERTEXT and from another person
114
128
  if ((0, exports.shouldIncrementChatUnread)(message)) {
@@ -116,6 +130,25 @@ const processMessage = async (message, { shouldProcessHistoryMsg, ev, creds, key
116
130
  }
117
131
  }
118
132
  const content = (0, messages_1.normalizeMessageContent)(message.message);
133
+ const senderId = message.key.participant || message.key.remoteJid;
134
+ if ((0, WABinary_1.isLidUser)(senderId)) {
135
+ const jid = (0, WABinary_1.lidToJid)(senderId);
136
+ if (message.key.participant) {
137
+ message.key.participant = jid;
138
+ }
139
+ else {
140
+ message.key.remoteJid = jid;
141
+ }
142
+ }
143
+ const mJids = content && content.contextInfo && content.contextInfo.mentionedJid ? content.contextInfo.mentionedJid : [];
144
+ for (let i = 0; i < mJids.length; i++) {
145
+ if ((0, WABinary_1.isLidUser)(mJids[i])) {
146
+ mJids[i] = (0, WABinary_1.lidToJid)(mJids[i]);
147
+ }
148
+ }
149
+ if (content && content.contextInfo && content.contextInfo.participant && (0, WABinary_1.isLidUser)(content.contextInfo.participant)) {
150
+ content.contextInfo.participant = (0, WABinary_1.lidToJid)(content.contextInfo.participant);
151
+ }
119
152
  // unarchive chat if it's a real message, or someone reacted to our message
120
153
  // and we've the unarchive chats setting on
121
154
  if ((isRealMsg || ((_b = (_a = content === null || content === void 0 ? void 0 : content.reactionMessage) === null || _a === void 0 ? void 0 : _a.key) === null || _b === void 0 ? void 0 : _b.fromMe))
@@ -137,14 +170,22 @@ const processMessage = async (message, { shouldProcessHistoryMsg, ev, creds, key
137
170
  isLatest,
138
171
  }, 'got history notification');
139
172
  if (process) {
140
- ev.emit('creds.update', {
141
- processedHistoryMessages: [
142
- ...(creds.processedHistoryMessages || []),
143
- { key: message.key, messageTimestamp: message.messageTimestamp }
144
- ]
145
- });
173
+ if (histNotification.syncType !== WAProto_1.proto.HistorySync.HistorySyncType.ON_DEMAND) {
174
+ ev.emit('creds.update', {
175
+ processedHistoryMessages: [
176
+ ...(creds.processedHistoryMessages || []),
177
+ { key: message.key, messageTimestamp: message.messageTimestamp }
178
+ ]
179
+ });
180
+ }
146
181
  const data = await (0, history_1.downloadAndProcessHistorySyncNotification)(histNotification, options);
147
- ev.emit('messaging-history.set', { ...data, isLatest });
182
+ ev.emit('messaging-history.set', {
183
+ ...data,
184
+ isLatest: histNotification.syncType !== WAProto_1.proto.HistorySync.HistorySyncType.ON_DEMAND
185
+ ? isLatest
186
+ : undefined,
187
+ peerDataRequestSessionId: histNotification.peerDataRequestSessionId
188
+ });
148
189
  }
149
190
  break;
150
191
  case WAProto_1.proto.Message.ProtocolMessage.Type.APP_STATE_SYNC_KEY_SHARE:
@@ -187,17 +228,41 @@ const processMessage = async (message, { shouldProcessHistoryMsg, ev, creds, key
187
228
  case WAProto_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_RESPONSE_MESSAGE:
188
229
  const response = protocolMsg.peerDataOperationRequestResponseMessage;
189
230
  if (response) {
231
+ placeholderResendCache === null || placeholderResendCache === void 0 ? void 0 : placeholderResendCache.del(response.stanzaId);
232
+ // TODO: IMPLEMENT HISTORY SYNC ETC (sticker uploads etc.).
190
233
  const { peerDataOperationResult } = response;
191
234
  for (const result of peerDataOperationResult) {
192
235
  const { placeholderMessageResendResponse: retryResponse } = result;
193
236
  if (retryResponse) {
194
237
  const webMessageInfo = WAProto_1.proto.WebMessageInfo.decode(retryResponse.webMessageInfoBytes);
195
- ev.emit('messages.update', [
196
- { key: webMessageInfo.key, update: { message: webMessageInfo.message } }
197
- ]);
238
+ // wait till another upsert event is available, don't want it to be part of the PDO response message
239
+ setTimeout(() => {
240
+ ev.emit('messages.upsert', {
241
+ messages: [webMessageInfo],
242
+ type: 'notify',
243
+ requestId: response.stanzaId
244
+ });
245
+ }, 500);
198
246
  }
199
247
  }
200
248
  }
249
+ case WAProto_1.proto.Message.ProtocolMessage.Type.MESSAGE_EDIT:
250
+ ev.emit('messages.update', [
251
+ {
252
+ // flip the sender / fromMe properties because they're in the perspective of the sender
253
+ key: { ...message.key, id: (_d = protocolMsg.key) === null || _d === void 0 ? void 0 : _d.id },
254
+ update: {
255
+ message: {
256
+ editedMessage: {
257
+ message: protocolMsg.editedMessage
258
+ }
259
+ },
260
+ messageTimestamp: protocolMsg.timestampMs
261
+ ? Math.floor((0, generics_1.toNumber)(protocolMsg.timestampMs) / 1000)
262
+ : message.messageTimestamp
263
+ }
264
+ }
265
+ ]);
201
266
  break;
202
267
  }
203
268
  }
@@ -208,11 +273,11 @@ const processMessage = async (message, { shouldProcessHistoryMsg, ev, creds, key
208
273
  };
209
274
  ev.emit('messages.reaction', [{
210
275
  reaction,
211
- key: content.reactionMessage.key,
276
+ key: (_e = content.reactionMessage) === null || _e === void 0 ? void 0 : _e.key,
212
277
  }]);
213
278
  }
214
279
  else if (message.messageStubType) {
215
- const jid = message.key.remoteJid;
280
+ const jid = (_f = message.key) === null || _f === void 0 ? void 0 : _f.remoteJid;
216
281
  //let actor = whatsappID (message.participant)
217
282
  let participants;
218
283
  const emitParticipantsUpdate = (action) => (ev.emit('group-participants.update', { id: jid, author: message.participant, participants, action }));
@@ -220,8 +285,15 @@ const processMessage = async (message, { shouldProcessHistoryMsg, ev, creds, key
220
285
  var _a;
221
286
  ev.emit('groups.update', [{ id: jid, ...update, author: (_a = message.participant) !== null && _a !== void 0 ? _a : undefined }]);
222
287
  };
288
+ const emitGroupRequestJoin = (participant, action, method) => {
289
+ ev.emit('group.join-request', { id: jid, author: message.participant, participant, action, method: method });
290
+ };
223
291
  const participantsIncludesMe = () => participants.find(jid => (0, WABinary_1.areJidsSameUser)(meId, jid));
224
292
  switch (message.messageStubType) {
293
+ case Types_1.WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER:
294
+ participants = message.messageStubParameters || [];
295
+ emitParticipantsUpdate('modify');
296
+ break;
225
297
  case Types_1.WAMessageStubType.GROUP_PARTICIPANT_LEAVE:
226
298
  case Types_1.WAMessageStubType.GROUP_PARTICIPANT_REMOVE:
227
299
  participants = message.messageStubParameters || [];
@@ -249,30 +321,41 @@ const processMessage = async (message, { shouldProcessHistoryMsg, ev, creds, key
249
321
  emitParticipantsUpdate('promote');
250
322
  break;
251
323
  case Types_1.WAMessageStubType.GROUP_CHANGE_ANNOUNCE:
252
- const announceValue = (_d = message.messageStubParameters) === null || _d === void 0 ? void 0 : _d[0];
324
+ const announceValue = (_g = message.messageStubParameters) === null || _g === void 0 ? void 0 : _g[0];
253
325
  emitGroupUpdate({ announce: announceValue === 'true' || announceValue === 'on' });
254
326
  break;
255
327
  case Types_1.WAMessageStubType.GROUP_CHANGE_RESTRICT:
256
- const restrictValue = (_e = message.messageStubParameters) === null || _e === void 0 ? void 0 : _e[0];
328
+ const restrictValue = (_h = message.messageStubParameters) === null || _h === void 0 ? void 0 : _h[0];
257
329
  emitGroupUpdate({ restrict: restrictValue === 'true' || restrictValue === 'on' });
258
330
  break;
259
331
  case Types_1.WAMessageStubType.GROUP_CHANGE_SUBJECT:
260
- const name = (_f = message.messageStubParameters) === null || _f === void 0 ? void 0 : _f[0];
332
+ const name = (_j = message.messageStubParameters) === null || _j === void 0 ? void 0 : _j[0];
261
333
  chat.name = name;
262
334
  emitGroupUpdate({ subject: name });
263
335
  break;
336
+ case Types_1.WAMessageStubType.GROUP_CHANGE_DESCRIPTION:
337
+ const description = (_k = message.messageStubParameters) === null || _k === void 0 ? void 0 : _k[0];
338
+ chat.description = description;
339
+ emitGroupUpdate({ desc: description });
340
+ break;
264
341
  case Types_1.WAMessageStubType.GROUP_CHANGE_INVITE_LINK:
265
- const code = (_g = message.messageStubParameters) === null || _g === void 0 ? void 0 : _g[0];
342
+ const code = (_l = message.messageStubParameters) === null || _l === void 0 ? void 0 : _l[0];
266
343
  emitGroupUpdate({ inviteCode: code });
267
344
  break;
268
345
  case Types_1.WAMessageStubType.GROUP_MEMBER_ADD_MODE:
269
- const memberAddValue = (_h = message.messageStubParameters) === null || _h === void 0 ? void 0 : _h[0];
346
+ const memberAddValue = (_m = message.messageStubParameters) === null || _m === void 0 ? void 0 : _m[0];
270
347
  emitGroupUpdate({ memberAddMode: memberAddValue === 'all_member_add' });
271
348
  break;
272
349
  case Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE:
273
- const approvalMode = (_j = message.messageStubParameters) === null || _j === void 0 ? void 0 : _j[0];
350
+ const approvalMode = (_o = message.messageStubParameters) === null || _o === void 0 ? void 0 : _o[0];
274
351
  emitGroupUpdate({ joinApprovalMode: approvalMode === 'on' });
275
352
  break;
353
+ case Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD:
354
+ const participant = (_p = message.messageStubParameters) === null || _p === void 0 ? void 0 : _p[0];
355
+ const action = (_q = message.messageStubParameters) === null || _q === void 0 ? void 0 : _q[1];
356
+ const method = (_r = message.messageStubParameters) === null || _r === void 0 ? void 0 : _r[2];
357
+ emitGroupRequestJoin(participant, action, method);
358
+ break;
276
359
  }
277
360
  }
278
361
  else if (content === null || content === void 0 ? void 0 : content.pollUpdateMessage) {
@@ -283,7 +366,7 @@ const processMessage = async (message, { shouldProcessHistoryMsg, ev, creds, key
283
366
  const meIdNormalised = (0, WABinary_1.jidNormalizedUser)(meId);
284
367
  const pollCreatorJid = (0, generics_1.getKeyAuthor)(creationMsgKey, meIdNormalised);
285
368
  const voterJid = (0, generics_1.getKeyAuthor)(message.key, meIdNormalised);
286
- const pollEncKey = (_k = pollMsg.messageContextInfo) === null || _k === void 0 ? void 0 : _k.messageSecret;
369
+ const pollEncKey = (_s = pollMsg.messageContextInfo) === null || _s === void 0 ? void 0 : _s.messageSecret;
287
370
  try {
288
371
  const voteMsg = decryptPollVote(content.pollUpdateMessage.vote, {
289
372
  pollEncKey,
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getNextPreKeysNode = exports.getNextPreKeys = exports.extractDeviceJids = exports.parseAndInjectE2ESessions = exports.xmppPreKey = exports.xmppSignedPreKey = exports.generateOrGetPreKeys = exports.getPreKeys = exports.createSignalIdentity = void 0;
4
+ const lodash_1 = require("lodash");
4
5
  const Defaults_1 = require("../Defaults");
5
6
  const WABinary_1 = require("../WABinary");
6
7
  const crypto_1 = require("./crypto");
@@ -66,46 +67,47 @@ const parseAndInjectE2ESessions = async (node, repository) => {
66
67
  for (const node of nodes) {
67
68
  (0, WABinary_1.assertNodeErrorFree)(node);
68
69
  }
69
- await Promise.all(nodes.map(async (node) => {
70
- const signedKey = (0, WABinary_1.getBinaryNodeChild)(node, 'skey');
71
- const key = (0, WABinary_1.getBinaryNodeChild)(node, 'key');
72
- const identity = (0, WABinary_1.getBinaryNodeChildBuffer)(node, 'identity');
73
- const jid = node.attrs.jid;
74
- const registrationId = (0, WABinary_1.getBinaryNodeChildUInt)(node, 'registration', 4);
75
- await repository.injectE2ESession({
76
- jid,
77
- session: {
78
- registrationId: registrationId,
79
- identityKey: (0, crypto_1.generateSignalPubKey)(identity),
80
- signedPreKey: extractKey(signedKey),
81
- preKey: extractKey(key)
82
- }
83
- });
84
- }));
70
+ // Most of the work in repository.injectE2ESession is CPU intensive, not IO
71
+ // So Promise.all doesn't really help here,
72
+ // but blocks even loop if we're using it inside keys.transaction, and it makes it "sync" actually
73
+ // This way we chunk it in smaller parts and between those parts we can yield to the event loop
74
+ // It's rare case when you need to E2E sessions for so many users, but it's possible
75
+ const chunkSize = 100;
76
+ const chunks = (0, lodash_1.chunk)(nodes, chunkSize);
77
+ for (const nodesChunk of chunks) {
78
+ await Promise.all(nodesChunk.map(async (node) => {
79
+ const signedKey = (0, WABinary_1.getBinaryNodeChild)(node, 'skey');
80
+ const key = (0, WABinary_1.getBinaryNodeChild)(node, 'key');
81
+ const identity = (0, WABinary_1.getBinaryNodeChildBuffer)(node, 'identity');
82
+ const jid = node.attrs.jid;
83
+ const registrationId = (0, WABinary_1.getBinaryNodeChildUInt)(node, 'registration', 4);
84
+ await repository.injectE2ESession({
85
+ jid,
86
+ session: {
87
+ registrationId: registrationId,
88
+ identityKey: (0, crypto_1.generateSignalPubKey)(identity),
89
+ signedPreKey: extractKey(signedKey),
90
+ preKey: extractKey(key)
91
+ }
92
+ });
93
+ }));
94
+ }
85
95
  };
86
96
  exports.parseAndInjectE2ESessions = parseAndInjectE2ESessions;
87
97
  const extractDeviceJids = (result, myJid, excludeZeroDevices) => {
88
- var _a;
89
98
  const { user: myUser, device: myDevice } = (0, WABinary_1.jidDecode)(myJid);
90
99
  const extracted = [];
91
- for (const node of result.content) {
92
- const list = (_a = (0, WABinary_1.getBinaryNodeChild)(node, 'list')) === null || _a === void 0 ? void 0 : _a.content;
93
- if (list && Array.isArray(list)) {
94
- for (const item of list) {
95
- const { user } = (0, WABinary_1.jidDecode)(item.attrs.jid);
96
- const devicesNode = (0, WABinary_1.getBinaryNodeChild)(item, 'devices');
97
- const deviceListNode = (0, WABinary_1.getBinaryNodeChild)(devicesNode, 'device-list');
98
- if (Array.isArray(deviceListNode === null || deviceListNode === void 0 ? void 0 : deviceListNode.content)) {
99
- for (const { tag, attrs } of deviceListNode.content) {
100
- const device = +attrs.id;
101
- if (tag === 'device' && // ensure the "device" tag
102
- (!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero
103
- (myUser !== user || myDevice !== device) && // either different user or if me user, not this device
104
- (device === 0 || !!attrs['key-index']) // ensure that "key-index" is specified for "non-zero" devices, produces a bad req otherwise
105
- ) {
106
- extracted.push({ user, device });
107
- }
108
- }
100
+ for (const userResult of result) {
101
+ const { devices, id } = userResult;
102
+ const { user } = (0, WABinary_1.jidDecode)(id);
103
+ const deviceList = devices === null || devices === void 0 ? void 0 : devices.deviceList;
104
+ if (Array.isArray(deviceList)) {
105
+ for (const { id: device, keyIndex } of deviceList) {
106
+ if ((!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero
107
+ (myUser !== user || myDevice !== device) && // either different user or if me user, not this device
108
+ (device === 0 || !!keyIndex) // ensure that "key-index" is specified for "non-zero" devices, produces a bad req otherwise
109
+ ) {
110
+ extracted.push({ user, device });
109
111
  }
110
112
  }
111
113
  }
@@ -1,11 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useMultiFileAuthState = void 0;
4
+ const async_mutex_1 = require("async-mutex");
4
5
  const promises_1 = require("fs/promises");
5
6
  const path_1 = require("path");
6
7
  const WAProto_1 = require("../../WAProto");
7
8
  const auth_utils_1 = require("./auth-utils");
8
9
  const generics_1 = require("./generics");
10
+ // We need to lock files due to the fact that we are using async functions to read and write files
11
+ // https://github.com/WhiskeySockets/VyzenBail/issues/794
12
+ // https://github.com/nodejs/node/issues/26338
13
+ // Use a Map to store mutexes for each file path
14
+ const fileLocks = new Map();
15
+ // Get or create a mutex for a specific file path
16
+ const getFileLock = (path) => {
17
+ let mutex = fileLocks.get(path);
18
+ if (!mutex) {
19
+ mutex = new async_mutex_1.Mutex();
20
+ fileLocks.set(path, mutex);
21
+ }
22
+ return mutex;
23
+ };
9
24
  /**
10
25
  * stores the full authentication state in a single folder.
11
26
  * Far more efficient than singlefileauthstate
@@ -14,13 +29,32 @@ const generics_1 = require("./generics");
14
29
  * Would recommend writing an auth state for use with a proper SQL or No-SQL DB
15
30
  * */
16
31
  const useMultiFileAuthState = async (folder) => {
17
- const writeData = (data, file) => {
18
- return (0, promises_1.writeFile)((0, path_1.join)(folder, fixFileName(file)), JSON.stringify(data, generics_1.BufferJSON.replacer));
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
+ const writeData = async (data, file) => {
34
+ const filePath = (0, path_1.join)(folder, fixFileName(file));
35
+ const mutex = getFileLock(filePath);
36
+ return mutex.acquire().then(async (release) => {
37
+ try {
38
+ await (0, promises_1.writeFile)(filePath, JSON.stringify(data, generics_1.BufferJSON.replacer));
39
+ }
40
+ finally {
41
+ release();
42
+ }
43
+ });
19
44
  };
20
45
  const readData = async (file) => {
21
46
  try {
22
- const data = await (0, promises_1.readFile)((0, path_1.join)(folder, fixFileName(file)), { encoding: 'utf-8' });
23
- return JSON.parse(data, generics_1.BufferJSON.reviver);
47
+ const filePath = (0, path_1.join)(folder, fixFileName(file));
48
+ const mutex = getFileLock(filePath);
49
+ return await mutex.acquire().then(async (release) => {
50
+ try {
51
+ const data = await (0, promises_1.readFile)(filePath, { encoding: 'utf-8' });
52
+ return JSON.parse(data, generics_1.BufferJSON.reviver);
53
+ }
54
+ finally {
55
+ release();
56
+ }
57
+ });
24
58
  }
25
59
  catch (error) {
26
60
  return null;
@@ -28,7 +62,18 @@ const useMultiFileAuthState = async (folder) => {
28
62
  };
29
63
  const removeData = async (file) => {
30
64
  try {
31
- await (0, promises_1.unlink)((0, path_1.join)(folder, fixFileName(file)));
65
+ const filePath = (0, path_1.join)(folder, fixFileName(file));
66
+ const mutex = getFileLock(filePath);
67
+ return mutex.acquire().then(async (release) => {
68
+ try {
69
+ await (0, promises_1.unlink)(filePath);
70
+ }
71
+ catch (_a) {
72
+ }
73
+ finally {
74
+ release();
75
+ }
76
+ });
32
77
  }
33
78
  catch (_a) {
34
79
  }
@@ -72,7 +117,7 @@ const useMultiFileAuthState = async (folder) => {
72
117
  }
73
118
  }
74
119
  },
75
- saveCreds: () => {
120
+ saveCreds: async () => {
76
121
  return writeData(creds, 'creds.json');
77
122
  }
78
123
  };