alipclutch-baileys 8.3.0 → 8.4.1

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 (120) hide show
  1. package/LICENSE +3 -1
  2. package/README.md +10 -9
  3. package/WAProto/GenerateStatics.sh +4 -0
  4. package/WAProto/WAProto.proto +4775 -0
  5. package/WAProto/index.d.ts +55057 -0
  6. package/WAProto/index.js +56887 -17535
  7. package/WAProto/index.ts.ts +53473 -0
  8. package/lib/Defaults/baileys-version.json +2 -2
  9. package/lib/Defaults/index.d.ts +16 -7
  10. package/lib/Defaults/index.js +90 -119
  11. package/lib/Socket/Client/index.d.ts +2 -3
  12. package/lib/Socket/Client/index.js +2 -3
  13. package/lib/Socket/Client/types.d.ts +0 -1
  14. package/lib/Socket/Client/types.js +0 -1
  15. package/lib/Socket/Client/websocket.d.ts +0 -1
  16. package/lib/Socket/Client/websocket.js +0 -1
  17. package/lib/Socket/business.d.ts +59 -58
  18. package/lib/Socket/chats.d.ts +45 -230
  19. package/lib/Socket/chats.js +139 -238
  20. package/lib/Socket/groups.d.ts +41 -32
  21. package/lib/Socket/groups.js +38 -23
  22. package/lib/Socket/index.d.ts +63 -64
  23. package/lib/Socket/index.js +2 -3
  24. package/lib/Socket/messages-recv.js +9 -65
  25. package/lib/Socket/messages-send.d.ts +49 -47
  26. package/lib/Socket/messages-send.js +584 -395
  27. package/lib/Socket/newsletter.d.ts +39 -37
  28. package/lib/Socket/newsletter.js +88 -123
  29. package/lib/Socket/setup.js +433 -0
  30. package/lib/Socket/{dugong.d.ts → setup.ts} +17 -52
  31. package/lib/Socket/socket.d.ts +10 -10
  32. package/lib/Socket/socket.js +62 -38
  33. package/lib/Socket/usync.d.ts +3 -4
  34. package/lib/Socket/usync.js +0 -1
  35. package/lib/Store/index.d.ts +1 -2
  36. package/lib/Store/index.js +1 -3
  37. package/lib/Store/make-in-memory-store.d.ts +24 -24
  38. package/lib/Store/make-in-memory-store.js +26 -14
  39. package/lib/Store/make-ordered-dictionary.d.ts +1 -1
  40. package/lib/Store/make-ordered-dictionary.js +2 -2
  41. package/lib/Types/Auth.d.ts +0 -7
  42. package/lib/Types/Call.d.ts +1 -1
  43. package/lib/Types/Chat.d.ts +14 -7
  44. package/lib/Types/Contact.d.ts +5 -1
  45. package/lib/Types/Events.d.ts +44 -2
  46. package/lib/Types/GroupMetadata.d.ts +11 -2
  47. package/lib/Types/Label.js +1 -1
  48. package/lib/Types/LabelAssociation.js +1 -1
  49. package/lib/Types/Message.d.ts +148 -21
  50. package/lib/Types/Message.js +0 -2
  51. package/lib/Types/Newsletter.d.ts +73 -97
  52. package/lib/Types/Newsletter.js +18 -38
  53. package/lib/Types/Socket.d.ts +17 -9
  54. package/lib/Types/index.d.ts +8 -1
  55. package/lib/Types/index.js +2 -2
  56. package/lib/Utils/auth-utils.d.ts +3 -3
  57. package/lib/Utils/auth-utils.js +6 -13
  58. package/lib/Utils/business.js +2 -2
  59. package/lib/Utils/chat-utils.d.ts +15 -16
  60. package/lib/Utils/chat-utils.js +36 -35
  61. package/lib/Utils/crypto.d.ts +15 -16
  62. package/lib/Utils/crypto.js +71 -29
  63. package/lib/Utils/decode-wa-message.d.ts +22 -6
  64. package/lib/Utils/decode-wa-message.js +65 -56
  65. package/lib/Utils/event-buffer.d.ts +2 -2
  66. package/lib/Utils/event-buffer.js +11 -7
  67. package/lib/Utils/generics.d.ts +17 -20
  68. package/lib/Utils/generics.js +95 -75
  69. package/lib/Utils/history.d.ts +4 -0
  70. package/lib/Utils/history.js +4 -6
  71. package/lib/Utils/link-preview.d.ts +2 -2
  72. package/lib/Utils/link-preview.js +34 -1
  73. package/lib/Utils/logger.d.ts +10 -3
  74. package/lib/Utils/lt-hash.d.ts +2 -2
  75. package/lib/Utils/lt-hash.js +6 -6
  76. package/lib/Utils/make-mutex.d.ts +2 -2
  77. package/lib/Utils/messages-media.d.ts +28 -24
  78. package/lib/Utils/messages-media.js +272 -111
  79. package/lib/Utils/messages.d.ts +13 -10
  80. package/lib/Utils/messages.js +323 -50
  81. package/lib/Utils/noise-handler.d.ts +10 -12
  82. package/lib/Utils/noise-handler.js +18 -23
  83. package/lib/Utils/process-message.d.ts +5 -4
  84. package/lib/Utils/process-message.js +108 -25
  85. package/lib/Utils/signal.d.ts +2 -1
  86. package/lib/Utils/signal.js +26 -26
  87. package/lib/Utils/use-multi-file-auth-state.d.ts +0 -1
  88. package/lib/Utils/use-multi-file-auth-state.js +51 -6
  89. package/lib/Utils/validate-connection.d.ts +3 -4
  90. package/lib/Utils/validate-connection.js +90 -66
  91. package/lib/WABinary/constants.d.ts +24 -27
  92. package/lib/WABinary/constants.js +1276 -13
  93. package/lib/WABinary/decode.d.ts +3 -4
  94. package/lib/WABinary/decode.js +26 -13
  95. package/lib/WABinary/encode.d.ts +1 -2
  96. package/lib/WABinary/encode.js +137 -152
  97. package/lib/WABinary/generic-utils.d.ts +1 -4
  98. package/lib/WABinary/generic-utils.js +37 -125
  99. package/lib/WABinary/jid-utils.d.ts +11 -5
  100. package/lib/WABinary/jid-utils.js +28 -5
  101. package/lib/WABinary/jid-utils.js.bak +83 -0
  102. package/lib/WAM/BinaryInfo.d.ts +2 -11
  103. package/lib/WAM/encode.d.ts +1 -2
  104. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +1 -1
  105. package/lib/index.d.ts +0 -1
  106. package/lib/index.js +27 -15
  107. package/package.json +18 -31
  108. package/engine-requirements.js +0 -10
  109. package/lib/Defaults/phonenumber-mcc.json +0 -223
  110. package/lib/Socket/Client/abstract-socket-client.d.ts +0 -17
  111. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  112. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  113. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  114. package/lib/Socket/Client/web-socket-client.d.ts +0 -12
  115. package/lib/Socket/Client/web-socket-client.js +0 -62
  116. package/lib/Socket/dugong.js +0 -483
  117. package/lib/Socket/registration.d.ts +0 -267
  118. package/lib/Socket/registration.js +0 -166
  119. package/lib/Store/make-cache-manager-store.d.ts +0 -13
  120. package/lib/Store/make-cache-manager-store.js +0 -83
@@ -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,14 +1,15 @@
1
1
  import { AxiosRequestConfig } from 'axios';
2
- import type { Logger } from 'pino';
3
2
  import { proto } from '../../WAProto';
4
- import { AuthenticationCreds, BaileysEventEmitter, SignalKeyStoreWithTransaction, SocketConfig } from '../Types';
3
+ import { AuthenticationCreds, BaileysEventEmitter, CacheStore, SignalKeyStoreWithTransaction, SocketConfig } from '../Types';
4
+ import { ILogger } from './logger';
5
5
  type ProcessMessageContext = {
6
6
  shouldProcessHistoryMsg: boolean;
7
+ placeholderResendCache?: CacheStore;
7
8
  creds: AuthenticationCreds;
8
9
  keyStore: SignalKeyStoreWithTransaction;
9
10
  ev: BaileysEventEmitter;
10
11
  getMessage: SocketConfig['getMessage'];
11
- logger?: Logger;
12
+ logger?: ILogger;
12
13
  options: AxiosRequestConfig<{}>;
13
14
  };
14
15
  /** Cleans a received message to further processing */
@@ -37,5 +38,5 @@ type PollContext = {
37
38
  * @returns list of SHA256 options
38
39
  */
39
40
  export declare function decryptPollVote({ encPayload, encIv }: proto.Message.IPollEncValue, { pollCreatorJid, pollMsgId, pollEncKey, voterJid, }: PollContext): proto.Message.PollVoteMessage;
40
- declare const processMessage: (message: proto.IWebMessageInfo, { shouldProcessHistoryMsg, ev, creds, keyStore, logger, options, getMessage }: ProcessMessageContext) => Promise<void>;
41
+ declare const processMessage: (message: proto.IWebMessageInfo, { shouldProcessHistoryMsg, placeholderResendCache, ev, creds, keyStore, logger, options, getMessage }: ProcessMessageContext) => Promise<void>;
41
42
  export default processMessage;
@@ -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
  import { SignalRepository } from '../Types';
2
2
  import { AuthenticationCreds, AuthenticationState, KeyPair, SignalIdentity, SignalKeyStore, SignedKeyPair } from '../Types/Auth';
3
3
  import { BinaryNode, JidWithDevice } from '../WABinary';
4
+ import { USyncQueryResultList } from '../WAUSync';
4
5
  export declare const createSignalIdentity: (wid: string, accountSignatureKey: Uint8Array) => SignalIdentity;
5
6
  export declare const getPreKeys: ({ get }: SignalKeyStore, min: number, limit: number) => Promise<{
6
7
  [id: string]: KeyPair;
@@ -15,7 +16,7 @@ export declare const generateOrGetPreKeys: (creds: AuthenticationCreds, range: n
15
16
  export declare const xmppSignedPreKey: (key: SignedKeyPair) => BinaryNode;
16
17
  export declare const xmppPreKey: (pair: KeyPair, id: number) => BinaryNode;
17
18
  export declare const parseAndInjectE2ESessions: (node: BinaryNode, repository: SignalRepository) => Promise<void>;
18
- export declare const extractDeviceJids: (result: BinaryNode, myJid: string, excludeZeroDevices: boolean) => JidWithDevice[];
19
+ export declare const extractDeviceJids: (result: USyncQueryResultList[], myJid: string, excludeZeroDevices: boolean) => JidWithDevice[];
19
20
  /**
20
21
  * get the next N keys for upload or processing
21
22
  * @param count number of pre-keys to get or generate
@@ -1,10 +1,10 @@
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");
7
- const lodash_1 = require("lodash")
8
8
  const generics_1 = require("./generics");
9
9
  const createSignalIdentity = (wid, accountSignatureKey) => {
10
10
  return {
@@ -59,61 +59,61 @@ const xmppPreKey = (pair, id) => ({
59
59
  exports.xmppPreKey = xmppPreKey;
60
60
  const parseAndInjectE2ESessions = async (node, repository) => {
61
61
  const extractKey = (key) => (key ? ({
62
- keyId: WABinary_1.getBinaryNodeChildUInt(key, 'id', 3),
63
- publicKey: crypto_1.generateSignalPubKey(WABinary_1.getBinaryNodeChildBuffer(key, 'value')),
64
- signature: WABinary_1.getBinaryNodeChildBuffer(key, 'signature')
65
- }) : undefined)
66
- const nodes = WABinary_1.getBinaryNodeChildren(WABinary_1.getBinaryNodeChild(node, 'list'), 'user')
62
+ keyId: (0, WABinary_1.getBinaryNodeChildUInt)(key, 'id', 3),
63
+ publicKey: (0, crypto_1.generateSignalPubKey)((0, WABinary_1.getBinaryNodeChildBuffer)(key, 'value')),
64
+ signature: (0, WABinary_1.getBinaryNodeChildBuffer)(key, 'signature'),
65
+ }) : undefined);
66
+ const nodes = (0, WABinary_1.getBinaryNodeChildren)((0, WABinary_1.getBinaryNodeChild)(node, 'list'), 'user');
67
67
  for (const node of nodes) {
68
- WABinary_1.assertNodeErrorFree(node)
68
+ (0, WABinary_1.assertNodeErrorFree)(node);
69
69
  }
70
70
  // Most of the work in repository.injectE2ESession is CPU intensive, not IO
71
71
  // So Promise.all doesn't really help here,
72
72
  // but blocks even loop if we're using it inside keys.transaction, and it makes it "sync" actually
73
73
  // This way we chunk it in smaller parts and between those parts we can yield to the event loop
74
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 = lodash_1.chunk(nodes, chunkSize)
75
+ const chunkSize = 100;
76
+ const chunks = (0, lodash_1.chunk)(nodes, chunkSize);
77
77
  for (const nodesChunk of chunks) {
78
78
  await Promise.all(nodesChunk.map(async (node) => {
79
- const signedKey = WABinary_1.getBinaryNodeChild(node, 'skey')
80
- const key = WABinary_1.getBinaryNodeChild(node, 'key')
81
- const identity = WABinary_1.getBinaryNodeChildBuffer(node, 'identity')
82
- const jid = node.attrs.jid
83
- const registrationId = WABinary_1.getBinaryNodeChildUInt(node, 'registration', 4)
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
84
  await repository.injectE2ESession({
85
85
  jid,
86
86
  session: {
87
87
  registrationId: registrationId,
88
- identityKey: crypto_1.generateSignalPubKey(identity),
88
+ identityKey: (0, crypto_1.generateSignalPubKey)(identity),
89
89
  signedPreKey: extractKey(signedKey),
90
90
  preKey: extractKey(key)
91
91
  }
92
- })
93
- }))
92
+ });
93
+ }));
94
94
  }
95
- }
95
+ };
96
96
  exports.parseAndInjectE2ESessions = parseAndInjectE2ESessions;
97
97
  const extractDeviceJids = (result, myJid, excludeZeroDevices) => {
98
- const { user: myUser, device: myDevice } = WABinary_1.jidDecode(myJid)
99
- const extracted = []
98
+ const { user: myUser, device: myDevice } = (0, WABinary_1.jidDecode)(myJid);
99
+ const extracted = [];
100
100
  for (const userResult of result) {
101
- const { devices, id } = userResult
102
- const { user } = WABinary_1.jidDecode(id)
103
- const deviceList = devices?.deviceList
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
104
  if (Array.isArray(deviceList)) {
105
105
  for (const { id: device, keyIndex } of deviceList) {
106
106
  if ((!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero
107
107
  (myUser !== user || myDevice !== device) && // either different user or if me user, not this device
108
108
  (device === 0 || !!keyIndex) // ensure that "key-index" is specified for "non-zero" devices, produces a bad req otherwise
109
109
  ) {
110
- extracted.push({ user, device })
110
+ extracted.push({ user, device });
111
111
  }
112
112
  }
113
113
  }
114
114
  }
115
- return extracted
116
- }
115
+ return extracted;
116
+ };
117
117
  exports.extractDeviceJids = extractDeviceJids;
118
118
  /**
119
119
  * get the next N keys for upload or processing
@@ -10,4 +10,3 @@ export declare const useMultiFileAuthState: (folder: string) => Promise<{
10
10
  state: AuthenticationState;
11
11
  saveCreds: () => Promise<void>;
12
12
  }>;
13
-
@@ -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/Baileys/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
  };
@@ -1,11 +1,10 @@
1
1
  import { proto } from '../../WAProto';
2
2
  import type { AuthenticationCreds, SignalCreds, SocketConfig } from '../Types';
3
3
  import { BinaryNode } from '../WABinary';
4
- export declare const generateMobileNode: (config: SocketConfig) => proto.IClientPayload;
5
4
  export declare const generateLoginNode: (userJid: string, config: SocketConfig) => proto.IClientPayload;
6
5
  export declare const generateRegistrationNode: ({ registrationId, signedPreKey, signedIdentityKey }: SignalCreds, config: SocketConfig) => proto.ClientPayload;
7
- export declare const configureSuccessfulPairing: (stanza: BinaryNode, { advSecretKey, signedIdentityKey, signalIdentities }: Pick<AuthenticationCreds, 'advSecretKey' | 'signedIdentityKey' | 'signalIdentities'>) => {
6
+ export declare const configureSuccessfulPairing: (stanza: BinaryNode, { advSecretKey, signedIdentityKey, signalIdentities }: Pick<AuthenticationCreds, "advSecretKey" | "signedIdentityKey" | "signalIdentities">) => {
8
7
  creds: Partial<AuthenticationCreds>;
9
8
  reply: BinaryNode;
10
- };
11
- export declare const encodeSignedDeviceIdentity: (account: proto.IADVSignedDeviceIdentity, includeSignatureKey: boolean) => Uint8Array;
9
+ };
10
+ export declare const encodeSignedDeviceIdentity: (account: proto.IADVSignedDeviceIdentity, includeSignatureKey: boolean) => Uint8Array<ArrayBufferLike>;