@ubedsockets/baileys 1.6.6 → 1.6.8

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 (87) hide show
  1. package/WAProto/GenerateStatics.sh +4 -3
  2. package/WAProto/WAProto.proto +511 -1215
  3. package/WAProto/index.js +131318 -59331
  4. package/lib/Defaults/index.js +92 -76
  5. package/lib/Signal/Group/ciphertext-message.js +5 -2
  6. package/lib/Signal/Group/group-session-builder.js +41 -7
  7. package/lib/Signal/Group/group_cipher.js +51 -37
  8. package/lib/Signal/Group/index.js +57 -12
  9. package/lib/Signal/Group/keyhelper.js +44 -7
  10. package/lib/Signal/Group/sender-chain-key.js +15 -7
  11. package/lib/Signal/Group/sender-key-distribution-message.js +11 -8
  12. package/lib/Signal/Group/sender-key-message.js +12 -9
  13. package/lib/Signal/Group/sender-key-name.js +5 -2
  14. package/lib/Signal/Group/sender-key-record.js +21 -9
  15. package/lib/Signal/Group/sender-key-state.js +42 -27
  16. package/lib/Signal/Group/sender-message-key.js +7 -4
  17. package/lib/Signal/libsignal.js +90 -347
  18. package/lib/Socket/Client/index.js +18 -3
  19. package/lib/Socket/Client/types.js +6 -4
  20. package/lib/Socket/Client/websocket.js +78 -21
  21. package/lib/Socket/business.js +43 -162
  22. package/lib/Socket/chats.js +249 -571
  23. package/lib/Socket/groups.js +99 -114
  24. package/lib/Socket/index.js +9 -11
  25. package/lib/Socket/messages-recv.js +559 -1277
  26. package/lib/Socket/messages-send.js +669 -674
  27. package/lib/Socket/newsletter.js +286 -149
  28. package/lib/Socket/socket.js +235 -548
  29. package/lib/Types/Auth.js +2 -2
  30. package/lib/Types/Call.js +2 -2
  31. package/lib/Types/Chat.js +4 -8
  32. package/lib/Types/Contact.js +2 -2
  33. package/lib/Types/Events.js +2 -2
  34. package/lib/Types/GroupMetadata.js +2 -2
  35. package/lib/Types/Label.js +5 -3
  36. package/lib/Types/LabelAssociation.js +5 -3
  37. package/lib/Types/Message.js +7 -11
  38. package/lib/Types/Product.js +2 -2
  39. package/lib/Types/Signal.js +2 -2
  40. package/lib/Types/Socket.js +2 -3
  41. package/lib/Types/State.js +2 -56
  42. package/lib/Types/USync.js +2 -2
  43. package/lib/Types/index.js +31 -15
  44. package/lib/Utils/auth-utils.js +136 -239
  45. package/lib/Utils/business.js +69 -66
  46. package/lib/Utils/chat-utils.js +238 -380
  47. package/lib/Utils/crypto.js +127 -56
  48. package/lib/Utils/decode-wa-message.js +63 -173
  49. package/lib/Utils/event-buffer.js +70 -174
  50. package/lib/Utils/generics.js +207 -159
  51. package/lib/Utils/history.js +53 -93
  52. package/lib/Utils/index.js +33 -22
  53. package/lib/Utils/link-preview.js +58 -17
  54. package/lib/Utils/logger.js +7 -3
  55. package/lib/Utils/lt-hash.js +46 -3
  56. package/lib/Utils/make-mutex.js +34 -24
  57. package/lib/Utils/messages-media.js +744 -483
  58. package/lib/Utils/messages.js +621 -411
  59. package/lib/Utils/noise-handler.js +99 -149
  60. package/lib/Utils/process-message.js +150 -459
  61. package/lib/Utils/signal.js +73 -112
  62. package/lib/Utils/use-multi-file-auth-state.js +27 -23
  63. package/lib/Utils/validate-connection.js +104 -74
  64. package/lib/WABinary/constants.js +11 -9
  65. package/lib/WABinary/decode.js +52 -49
  66. package/lib/WABinary/encode.js +49 -19
  67. package/lib/WABinary/generic-utils.js +43 -46
  68. package/lib/WABinary/index.js +21 -6
  69. package/lib/WABinary/jid-utils.js +45 -72
  70. package/lib/WABinary/types.js +2 -2
  71. package/lib/WAM/BinaryInfo.js +5 -2
  72. package/lib/WAM/constants.js +11958 -19461
  73. package/lib/WAM/encode.js +22 -17
  74. package/lib/WAM/index.js +19 -4
  75. package/lib/WAUSync/Protocols/USyncContactProtocol.js +13 -33
  76. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +14 -11
  77. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +11 -8
  78. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +13 -9
  79. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +22 -20
  80. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +8 -13
  81. package/lib/WAUSync/Protocols/index.js +20 -6
  82. package/lib/WAUSync/USyncQuery.js +35 -44
  83. package/lib/WAUSync/USyncUser.js +5 -10
  84. package/lib/WAUSync/index.js +19 -4
  85. package/lib/index.js +70 -11
  86. package/package.json +60 -100
  87. package/engine-requirements.js +0 -10
@@ -1,28 +1,81 @@
1
- import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes } from 'crypto';
2
- import * as curve from 'libsignal/src/curve.js';
3
- import { KEY_BUNDLE_TYPE } from '../Defaults/index.js';
4
- export { md5, hkdf } from 'whatsapp-rust-bridge';
5
- // insure browser & node compatibility
6
- const { subtle } = globalThis.crypto;
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.signedKeyPair = exports.Curve = exports.generateSignalPubKey = void 0;
37
+ exports.aesEncryptGCM = aesEncryptGCM;
38
+ exports.aesDecryptGCM = aesDecryptGCM;
39
+ exports.aesEncryptCTR = aesEncryptCTR;
40
+ exports.aesDecryptCTR = aesDecryptCTR;
41
+ exports.aesDecrypt = aesDecrypt;
42
+ exports.aesDecryptWithIV = aesDecryptWithIV;
43
+ exports.aesEncrypt = aesEncrypt;
44
+ exports.aesEncrypWithIV = aesEncrypWithIV;
45
+ exports.hmacSign = hmacSign;
46
+ exports.sha256 = sha256;
47
+ exports.md5 = md5;
48
+ exports.hkdf = hkdf;
49
+ exports.derivePairingCodeKey = derivePairingCodeKey;
50
+ const crypto_1 = require("crypto");
51
+ const libsignal = __importStar(require("libsignal"));
52
+ const Defaults_1 = require("../Defaults");
53
+
54
+ const webCrypto = globalThis.crypto ? globalThis.crypto : crypto_1.webcrypto;
55
+ const subtle = webCrypto ? webCrypto.subtle : undefined;
56
+
7
57
  /** prefix version byte to the pub keys, required for some curve crypto functions */
8
- export const generateSignalPubKey = (pubKey) => pubKey.length === 33 ? pubKey : Buffer.concat([KEY_BUNDLE_TYPE, pubKey]);
9
- export const Curve = {
58
+ const generateSignalPubKey = (pubKey) => (pubKey.length === 33
59
+ ? pubKey
60
+ : Buffer.concat([Defaults_1.KEY_BUNDLE_TYPE, pubKey]));
61
+ exports.generateSignalPubKey = generateSignalPubKey;
62
+ exports.Curve = {
10
63
  generateKeyPair: () => {
11
- const { pubKey, privKey } = curve.generateKeyPair();
64
+ const { pubKey, privKey } = libsignal.curve.generateKeyPair();
12
65
  return {
13
66
  private: Buffer.from(privKey),
14
- // remove version byte
67
+
15
68
  public: Buffer.from(pubKey.slice(1))
16
69
  };
17
70
  },
18
71
  sharedKey: (privateKey, publicKey) => {
19
- const shared = curve.calculateAgreement(generateSignalPubKey(publicKey), privateKey);
72
+ const shared = libsignal.curve.calculateAgreement((0, exports.generateSignalPubKey)(publicKey), privateKey);
20
73
  return Buffer.from(shared);
21
74
  },
22
- sign: (privateKey, buf) => curve.calculateSignature(privateKey, buf),
75
+ sign: (privateKey, buf) => (libsignal.curve.calculateSignature(privateKey, buf)),
23
76
  verify: (pubKey, message, signature) => {
24
77
  try {
25
- curve.verifySignature(generateSignalPubKey(pubKey), message, signature);
78
+ libsignal.curve.verifySignature((0, exports.generateSignalPubKey)(pubKey), message, signature);
26
79
  return true;
27
80
  }
28
81
  catch (error) {
@@ -30,19 +83,20 @@ export const Curve = {
30
83
  }
31
84
  }
32
85
  };
33
- export const signedKeyPair = (identityKeyPair, keyId) => {
34
- const preKey = Curve.generateKeyPair();
35
- const pubKey = generateSignalPubKey(preKey.public);
36
- const signature = Curve.sign(identityKeyPair.private, pubKey);
86
+ const signedKeyPair = (identityKeyPair, keyId) => {
87
+ const preKey = exports.Curve.generateKeyPair();
88
+ const pubKey = (0, exports.generateSignalPubKey)(preKey.public);
89
+ const signature = exports.Curve.sign(identityKeyPair.private, pubKey);
37
90
  return { keyPair: preKey, signature, keyId };
38
91
  };
92
+ exports.signedKeyPair = signedKeyPair;
39
93
  const GCM_TAG_LENGTH = 128 >> 3;
40
94
  /**
41
95
  * encrypt AES 256 GCM;
42
96
  * where the tag tag is suffixed to the ciphertext
43
97
  * */
44
- export function aesEncryptGCM(plaintext, key, iv, additionalData) {
45
- const cipher = createCipheriv('aes-256-gcm', key, iv);
98
+ function aesEncryptGCM(plaintext, key, iv, additionalData) {
99
+ const cipher = (0, crypto_1.createCipheriv)('aes-256-gcm', key, iv);
46
100
  cipher.setAAD(additionalData);
47
101
  return Buffer.concat([cipher.update(plaintext), cipher.final(), cipher.getAuthTag()]);
48
102
  }
@@ -50,69 +104,86 @@ export function aesEncryptGCM(plaintext, key, iv, additionalData) {
50
104
  * decrypt AES 256 GCM;
51
105
  * where the auth tag is suffixed to the ciphertext
52
106
  * */
53
- export function aesDecryptGCM(ciphertext, key, iv, additionalData) {
54
- const decipher = createDecipheriv('aes-256-gcm', key, iv);
55
- // decrypt additional adata
107
+ function aesDecryptGCM(ciphertext, key, iv, additionalData) {
108
+ const decipher = (0, crypto_1.createDecipheriv)('aes-256-gcm', key, iv);
109
+
56
110
  const enc = ciphertext.slice(0, ciphertext.length - GCM_TAG_LENGTH);
57
111
  const tag = ciphertext.slice(ciphertext.length - GCM_TAG_LENGTH);
58
- // set additional data
112
+
59
113
  decipher.setAAD(additionalData);
60
114
  decipher.setAuthTag(tag);
61
115
  return Buffer.concat([decipher.update(enc), decipher.final()]);
62
116
  }
63
- export function aesEncryptCTR(plaintext, key, iv) {
64
- const cipher = createCipheriv('aes-256-ctr', key, iv);
117
+ function aesEncryptCTR(plaintext, key, iv) {
118
+ const cipher = (0, crypto_1.createCipheriv)('aes-256-ctr', key, iv);
65
119
  return Buffer.concat([cipher.update(plaintext), cipher.final()]);
66
120
  }
67
- export function aesDecryptCTR(ciphertext, key, iv) {
68
- const decipher = createDecipheriv('aes-256-ctr', key, iv);
121
+ function aesDecryptCTR(ciphertext, key, iv) {
122
+ const decipher = (0, crypto_1.createDecipheriv)('aes-256-ctr', key, iv);
69
123
  return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
70
124
  }
71
125
  /** decrypt AES 256 CBC; where the IV is prefixed to the buffer */
72
- export function aesDecrypt(buffer, key) {
73
- return aesDecryptWithIV(buffer.subarray(16), key, buffer.subarray(0, 16));
126
+ function aesDecrypt(buffer, key) {
127
+ return aesDecryptWithIV(buffer.slice(16, buffer.length), key, buffer.slice(0, 16));
74
128
  }
75
129
  /** decrypt AES 256 CBC */
76
- export function aesDecryptWithIV(buffer, key, IV) {
77
- const aes = createDecipheriv('aes-256-cbc', key, IV);
130
+ function aesDecryptWithIV(buffer, key, IV) {
131
+ const aes = (0, crypto_1.createDecipheriv)('aes-256-cbc', key, IV);
78
132
  return Buffer.concat([aes.update(buffer), aes.final()]);
79
133
  }
80
- // encrypt AES 256 CBC; where a random IV is prefixed to the buffer
81
- export function aesEncrypt(buffer, key) {
82
- const IV = randomBytes(16);
83
- const aes = createCipheriv('aes-256-cbc', key, IV);
84
- return Buffer.concat([IV, aes.update(buffer), aes.final()]); // prefix IV to the buffer
134
+
135
+ function aesEncrypt(buffer, key) {
136
+ const IV = (0, crypto_1.randomBytes)(16);
137
+ const aes = (0, crypto_1.createCipheriv)('aes-256-cbc', key, IV);
138
+ return Buffer.concat([IV, aes.update(buffer), aes.final()]);
139
+ }
140
+
141
+ function aesEncrypWithIV(buffer, key, IV) {
142
+ const aes = (0, crypto_1.createCipheriv)('aes-256-cbc', key, IV);
143
+ return Buffer.concat([aes.update(buffer), aes.final()]);
144
+ }
145
+
146
+ function hmacSign(buffer, key, variant = 'sha256') {
147
+ return (0, crypto_1.createHmac)(variant, key).update(buffer).digest();
85
148
  }
86
- // encrypt AES 256 CBC with a given IV
87
- export function aesEncrypWithIV(buffer, key, IV) {
88
- const aes = createCipheriv('aes-256-cbc', key, IV);
89
- return Buffer.concat([aes.update(buffer), aes.final()]); // prefix IV to the buffer
149
+ function sha256(buffer) {
150
+ return (0, crypto_1.createHash)('sha256').update(buffer).digest();
90
151
  }
91
- // sign HMAC using SHA 256
92
- export function hmacSign(buffer, key, variant = 'sha256') {
93
- return createHmac(variant, key).update(buffer).digest();
152
+ function md5(buffer) {
153
+ return (0, crypto_1.createHash)('md5').update(buffer).digest();
94
154
  }
95
- export function sha256(buffer) {
96
- return createHash('sha256').update(buffer).digest();
155
+
156
+ async function hkdf(buffer, expandedLength, info) {
157
+ if (!subtle) throw new Error("WebCrypto 'subtle' is not available. Please update your Node.js version.");
158
+ const inputKeyMaterial = buffer instanceof Uint8Array
159
+ ? buffer
160
+ : new Uint8Array(buffer);
161
+ const salt = info.salt ? new Uint8Array(info.salt) : new Uint8Array(0);
162
+ const infoBytes = info.info
163
+ ? new TextEncoder().encode(info.info)
164
+ : new Uint8Array(0);
165
+ const importedKey = await subtle.importKey('raw', inputKeyMaterial, { name: 'HKDF' }, false, ['deriveBits']);
166
+ const derivedBits = await subtle.deriveBits({
167
+ name: 'HKDF',
168
+ hash: 'SHA-256',
169
+ salt: salt,
170
+ info: infoBytes
171
+ }, importedKey, expandedLength * 8
172
+ );
173
+ return Buffer.from(derivedBits);
97
174
  }
98
- export async function derivePairingCodeKey(pairingCode, salt) {
99
- // Convert inputs to formats Web Crypto API can work with
175
+ async function derivePairingCodeKey(pairingCode, salt) {
176
+ if (!subtle) throw new Error("WebCrypto 'subtle' is not available. Please update your Node.js version.");
100
177
  const encoder = new TextEncoder();
101
178
  const pairingCodeBuffer = encoder.encode(pairingCode);
102
- const saltBuffer = new Uint8Array(salt instanceof Uint8Array ? salt : new Uint8Array(salt));
103
- // Import the pairing code as key material
104
- const keyMaterial = await subtle.importKey('raw', pairingCodeBuffer, { name: 'PBKDF2' }, false, [
105
- 'deriveBits'
106
- ]);
107
- // Derive bits using PBKDF2 with the same parameters
108
- // 2 << 16 = 131,072 iterations
179
+ const saltBuffer = salt instanceof Uint8Array ? salt : new Uint8Array(salt);
180
+ const keyMaterial = await subtle.importKey('raw', pairingCodeBuffer, { name: 'PBKDF2' }, false, ['deriveBits']);
109
181
  const derivedBits = await subtle.deriveBits({
110
182
  name: 'PBKDF2',
111
183
  salt: saltBuffer,
112
184
  iterations: 2 << 16,
113
185
  hash: 'SHA-256'
114
- }, keyMaterial, 32 * 8 // 32 bytes * 8 = 256 bits
186
+ }, keyMaterial, 32 * 8
115
187
  );
116
188
  return Buffer.from(derivedBits);
117
189
  }
118
- //# sourceMappingURL=crypto.js.map
@@ -1,42 +1,14 @@
1
- import { Boom } from '@hapi/boom';
2
- import { proto } from '../../WAProto/index.js';
3
- import { areJidsSameUser, isHostedLidUser, isHostedPnUser, isJidBroadcast, isJidGroup, isJidMetaAI, isJidNewsletter, isJidStatusBroadcast, isLidUser, isPnUser
4
- // transferDevice
5
- } from '../WABinary/index.js';
6
- import { unpadRandomMax16 } from './generics.js';
7
- export const getDecryptionJid = async (sender, repository) => {
8
- if (isLidUser(sender) || isHostedLidUser(sender)) {
9
- return sender;
10
- }
11
- const mapped = await repository.lidMapping.getLIDForPN(sender);
12
- return mapped || sender;
13
- };
14
- const storeMappingFromEnvelope = async (stanza, sender, repository, decryptionJid, logger) => {
15
- // TODO: Handle hosted IDs
16
- const { senderAlt } = extractAddressingContext(stanza);
17
- if (senderAlt && isLidUser(senderAlt) && isPnUser(sender) && decryptionJid === sender) {
18
- try {
19
- await repository.lidMapping.storeLIDPNMappings([{ lid: senderAlt, pn: sender }]);
20
- await repository.migrateSession(sender, senderAlt);
21
- logger.debug({ sender, senderAlt }, 'Stored LID mapping from envelope');
22
- }
23
- catch (error) {
24
- logger.warn({ sender, senderAlt, error }, 'Failed to store LID mapping');
25
- }
26
- }
27
- };
28
- export const NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node';
29
- export const MISSING_KEYS_ERROR_TEXT = 'Key used already or never filled';
30
- export const ACCOUNT_RESTRICTED_TEXT = 'Your account has been restricted';
31
- // Retry configuration for failed decryption
32
- export const DECRYPTION_RETRY_CONFIG = {
33
- maxRetries: 3,
34
- baseDelayMs: 100,
35
- sessionRecordErrors: ['No session record', 'SessionError: No session record']
36
- };
37
- /** NACK reason codes we send to the server (client → server) */
38
- export const NACK_REASONS = {
39
- SenderReachoutTimelocked: 463,
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decryptMessageNode = exports.NACK_REASONS = exports.MISSING_KEYS_ERROR_TEXT = exports.NO_MESSAGE_FOUND_ERROR_TEXT = void 0;
4
+ exports.decodeMessageNode = decodeMessageNode;
5
+ const boom_1 = require("@hapi/boom");
6
+ const WAProto_1 = require("../../WAProto");
7
+ const WABinary_1 = require("../WABinary");
8
+ const generics_1 = require("./generics");
9
+ exports.NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node';
10
+ exports.MISSING_KEYS_ERROR_TEXT = 'Key used already or never filled';
11
+ exports.NACK_REASONS = {
40
12
  ParsingError: 487,
41
13
  UnrecognizedStanza: 488,
42
14
  UnrecognizedStanzaClass: 489,
@@ -51,153 +23,90 @@ export const NACK_REASONS = {
51
23
  UnsupportedLIDGroup: 551,
52
24
  DBOperationFailed: 552
53
25
  };
54
- /**
55
- * Server-side error codes returned in ack stanzas (server → client) that we
56
- * currently have dedicated handlers for. Extend as more handlers are added.
57
- * Distinct from the client-side NackReason enum (WAWebCreateNackFromStanza).
58
- */
59
- export const SERVER_ERROR_CODES = {
60
- /**
61
- * 1:1 message missing privacy token (tctoken). Usually means the account is
62
- * restricted: WhatsApp blocks starting new chats but preserves existing ones,
63
- * since established chats already carry a tctoken.
64
- */
65
- MessageAccountRestriction: '463',
66
- /** Stanza validation failure (SMAX_INVALID) — likely stale device session */
67
- SmaxInvalid: '479'
68
- };
69
- export const extractAddressingContext = (stanza) => {
70
- let senderAlt;
71
- let recipientAlt;
72
- const sender = stanza.attrs.participant || stanza.attrs.from;
73
- const addressingMode = stanza.attrs.addressing_mode || (sender?.endsWith('lid') ? 'lid' : 'pn');
74
- if (addressingMode === 'lid') {
75
- // Message is LID-addressed: sender is LID, extract corresponding PN
76
- // without device data
77
- senderAlt = stanza.attrs.participant_pn || stanza.attrs.sender_pn || stanza.attrs.peer_recipient_pn;
78
- recipientAlt = stanza.attrs.recipient_pn;
79
- // with device data
80
- //if (sender && senderAlt) senderAlt = transferDevice(sender, senderAlt)
81
- }
82
- else {
83
- // Message is PN-addressed: sender is PN, extract corresponding LID
84
- // without device data
85
- senderAlt = stanza.attrs.participant_lid || stanza.attrs.sender_lid || stanza.attrs.peer_recipient_lid;
86
- recipientAlt = stanza.attrs.recipient_lid;
87
- //with device data
88
- //if (sender && senderAlt) senderAlt = transferDevice(sender, senderAlt)
89
- }
90
- return {
91
- addressingMode,
92
- senderAlt,
93
- recipientAlt
94
- };
95
- };
96
26
  /**
97
27
  * Decode the received node as a message.
98
28
  * @note this will only parse the message, not decrypt it
99
29
  */
100
- export function decodeMessageNode(stanza, meId, meLid) {
30
+ function decodeMessageNode(stanza, meId, meLid) {
31
+ var _a, _b, _c, _d, _e, _f, _g;
101
32
  let msgType;
102
33
  let chatId;
103
34
  let author;
104
- let fromMe = false;
105
35
  const msgId = stanza.attrs.id;
106
36
  const from = stanza.attrs.from;
37
+ const senderPn = (_a = stanza === null || stanza === void 0 ? void 0 : stanza.attrs) === null || _a === void 0 ? void 0 : _a.sender_pn;
38
+ const senderLid = (_b = stanza === null || stanza === void 0 ? void 0 : stanza.attrs) === null || _b === void 0 ? void 0 : _b.sender_lid;
107
39
  const participant = stanza.attrs.participant;
40
+ const participantLid = (_c = stanza === null || stanza === void 0 ? void 0 : stanza.attrs) === null || _c === void 0 ? void 0 : _c.participant_lid;
108
41
  const recipient = stanza.attrs.recipient;
109
- if (!msgId) {
110
- throw new Boom('Invalid message stanza: missing id attribute', { data: stanza });
111
- }
112
- if (!from) {
113
- throw new Boom('Invalid message stanza: missing from attribute', { data: stanza });
114
- }
115
- const addressingContext = extractAddressingContext(stanza);
116
- const isMe = (jid) => areJidsSameUser(jid, meId);
117
- const isMeLid = (jid) => areJidsSameUser(jid, meLid);
118
- if (isPnUser(from) || isLidUser(from) || isHostedLidUser(from) || isHostedPnUser(from)) {
119
- if (recipient && !isJidMetaAI(recipient)) {
42
+ const isMe = (jid) => (0, WABinary_1.areJidsSameUser)(jid, meId);
43
+ const isMeLid = (jid) => (0, WABinary_1.areJidsSameUser)(jid, meLid);
44
+ if ((0, WABinary_1.isJidUser)(from) || (0, WABinary_1.isLidUser)(from)) {
45
+ if (recipient && !(0, WABinary_1.isJidMetaAi)(recipient)) {
120
46
  if (!isMe(from) && !isMeLid(from)) {
121
- throw new Boom('receipient present, but msg not from me', { data: stanza });
122
- }
123
- if (isMe(from) || isMeLid(from)) {
124
- fromMe = true;
47
+ throw new boom_1.Boom('receipient present, but msg not from me', { data: stanza });
125
48
  }
126
49
  chatId = recipient;
127
50
  }
128
51
  else {
129
- // Peer-routed self stanzas (history sync, app-state sync, etc.) arrive
130
- // with `from` set to our own device but no `recipient` attribute —
131
- // still mark as fromMe so self-only protocolMessage handlers run.
132
- if (isMe(from) || isMeLid(from)) {
133
- fromMe = true;
134
- }
135
52
  chatId = from;
136
53
  }
137
54
  msgType = 'chat';
138
55
  author = from;
139
56
  }
140
- else if (isJidGroup(from)) {
57
+ else if ((0, WABinary_1.isJidGroup)(from)) {
141
58
  if (!participant) {
142
- throw new Boom('No participant in group message');
143
- }
144
- if (isMe(participant) || isMeLid(participant)) {
145
- fromMe = true;
59
+ throw new boom_1.Boom('No participant in group message');
146
60
  }
147
61
  msgType = 'group';
148
62
  author = participant;
149
63
  chatId = from;
150
64
  }
151
- else if (isJidBroadcast(from)) {
65
+ else if ((0, WABinary_1.isJidNewsletter)(from)) {
66
+ msgType = 'newsletter';
67
+ author = from;
68
+ chatId = from;
69
+ }
70
+ else if ((0, WABinary_1.isJidBroadcast)(from)) {
152
71
  if (!participant) {
153
- throw new Boom('No participant in group message');
72
+ throw new boom_1.Boom('No participant in group message');
154
73
  }
155
74
  const isParticipantMe = isMe(participant);
156
- if (isJidStatusBroadcast(from)) {
75
+ if ((0, WABinary_1.isJidStatusBroadcast)(from)) {
157
76
  msgType = isParticipantMe ? 'direct_peer_status' : 'other_status';
158
77
  }
159
78
  else {
160
79
  msgType = isParticipantMe ? 'peer_broadcast' : 'other_broadcast';
161
80
  }
162
- fromMe = isParticipantMe;
163
81
  chatId = from;
164
82
  author = participant;
165
83
  }
166
- else if (isJidNewsletter(from)) {
167
- msgType = 'newsletter';
168
- chatId = from;
169
- author = from;
170
- if (isMe(from) || isMeLid(from)) {
171
- fromMe = true;
172
- }
173
- }
174
84
  else {
175
- throw new Boom('Unknown message type', { data: stanza });
85
+ throw new boom_1.Boom('Unknown message type', { data: stanza });
176
86
  }
177
- const pushname = stanza?.attrs?.notify;
87
+ const fromMe = (0, WABinary_1.isJidNewsletter)(from) ? !!((_d = stanza.attrs) === null || _d === void 0 ? void 0 : _d.is_sender) || false : ((0, WABinary_1.isLidUser)(from) ? isMeLid : isMe)(stanza.attrs.participant || stanza.attrs.from);
88
+ const pushname = (_e = stanza === null || stanza === void 0 ? void 0 : stanza.attrs) === null || _e === void 0 ? void 0 : _e.notify;
178
89
  const key = {
179
90
  remoteJid: chatId,
180
- remoteJidAlt: !isJidGroup(chatId) ? addressingContext.senderAlt : undefined,
181
- remoteJidUsername: !isJidGroup(chatId)
182
- ? stanza.attrs.peer_recipient_username || stanza.attrs.recipient_username
183
- : undefined,
184
91
  fromMe,
185
92
  id: msgId,
93
+ senderPn,
94
+ senderLid,
186
95
  participant,
187
- participantAlt: isJidGroup(chatId) ? addressingContext.senderAlt : undefined,
188
- participantUsername: stanza.attrs.participant ? stanza.attrs.participant_username : undefined,
189
- addressingMode: addressingContext.addressingMode,
190
- ...(msgType === 'newsletter' && stanza.attrs.server_id ? { server_id: stanza.attrs.server_id } : {})
96
+ participantLid,
97
+ 'server_id': (_f = stanza.attrs) === null || _f === void 0 ? void 0 : _f.server_id
191
98
  };
192
99
  const fullMessage = {
193
100
  key,
194
- category: stanza.attrs.category,
195
101
  messageTimestamp: +stanza.attrs.t,
196
102
  pushName: pushname,
197
- broadcast: isJidBroadcast(from)
103
+ broadcast: (0, WABinary_1.isJidBroadcast)(from)
198
104
  };
105
+ if (msgType === 'newsletter') {
106
+ fullMessage.newsletterServerId = +((_g = stanza.attrs) === null || _g === void 0 ? void 0 : _g.server_id);
107
+ }
199
108
  if (key.fromMe) {
200
- fullMessage.status = proto.WebMessageInfo.Status.SERVER_ACK;
109
+ fullMessage.status = WAProto_1.proto.WebMessageInfo.Status.SERVER_ACK;
201
110
  }
202
111
  return {
203
112
  fullMessage,
@@ -205,26 +114,24 @@ export function decodeMessageNode(stanza, meId, meLid) {
205
114
  sender: msgType === 'chat' ? author : chatId
206
115
  };
207
116
  }
208
- export const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
117
+ const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
209
118
  const { fullMessage, author, sender } = decodeMessageNode(stanza, meId, meLid);
210
119
  return {
211
120
  fullMessage,
212
121
  category: stanza.attrs.category,
213
122
  author,
214
123
  async decrypt() {
124
+ var _a;
215
125
  let decryptables = 0;
216
126
  if (Array.isArray(stanza.content)) {
217
127
  for (const { tag, attrs, content } of stanza.content) {
218
128
  if (tag === 'verified_name' && content instanceof Uint8Array) {
219
- const cert = proto.VerifiedNameCertificate.decode(content);
220
- const details = proto.VerifiedNameCertificate.Details.decode(cert.details);
129
+ const cert = WAProto_1.proto.VerifiedNameCertificate.decode(content);
130
+ const details = WAProto_1.proto.VerifiedNameCertificate.Details.decode(cert.details);
221
131
  fullMessage.verifiedBizName = details.verifiedName;
222
132
  }
223
133
  if (tag === 'unavailable' && attrs.type === 'view_once') {
224
- fullMessage.key.isViewOnce = true; // TODO: remove from here and add a STUB TYPE
225
- }
226
- if (attrs.count && tag === 'enc') {
227
- fullMessage.retryCount = Number(attrs.count);
134
+ fullMessage.key.isViewOnce = true;
228
135
  }
229
136
  if (tag !== 'enc' && tag !== 'plaintext') {
230
137
  continue;
@@ -234,11 +141,6 @@ export const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
234
141
  }
235
142
  decryptables += 1;
236
143
  let msgBuffer;
237
- const decryptionJid = await getDecryptionJid(author, repository);
238
- if (tag !== 'plaintext') {
239
- // TODO: Handle hosted devices
240
- await storeMappingFromEnvelope(stanza, author, repository, decryptionJid, logger);
241
- }
242
144
  try {
243
145
  const e2eType = tag === 'plaintext' ? 'plaintext' : attrs.type;
244
146
  switch (e2eType) {
@@ -251,8 +153,9 @@ export const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
251
153
  break;
252
154
  case 'pkmsg':
253
155
  case 'msg':
156
+ const user = (0, WABinary_1.isJidUser)(sender) ? sender : author;
254
157
  msgBuffer = await repository.decryptMessage({
255
- jid: decryptionJid,
158
+ jid: user,
256
159
  type: e2eType,
257
160
  ciphertext: content
258
161
  });
@@ -260,13 +163,15 @@ export const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
260
163
  case 'plaintext':
261
164
  msgBuffer = content;
262
165
  break;
166
+ case undefined:
167
+ msgBuffer = content;
168
+ break;
263
169
  default:
264
170
  throw new Error(`Unknown e2e type: ${e2eType}`);
265
171
  }
266
- let msg = proto.Message.decode(e2eType !== 'plaintext' ? unpadRandomMax16(msgBuffer) : msgBuffer);
267
- msg = msg.deviceSentMessage?.message || msg;
172
+ let msg = WAProto_1.proto.Message.decode(e2eType !== 'plaintext' ? (0, generics_1.unpadRandomMax16)(msgBuffer) : msgBuffer);
173
+ msg = ((_a = msg === null || msg === void 0 ? void 0 : msg.deviceSentMessage) === null || _a === void 0 ? void 0 : _a.message) || msg;
268
174
  if (msg.senderKeyDistributionMessage) {
269
- //eslint-disable-next-line max-depth
270
175
  try {
271
176
  await repository.processSenderKeyDistributionMessage({
272
177
  authorJid: author,
@@ -274,7 +179,7 @@ export const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
274
179
  });
275
180
  }
276
181
  catch (err) {
277
- logger.error({ key: fullMessage.key, err }, 'failed to process sender key distribution message');
182
+ logger.error({ key: fullMessage.key, err }, 'failed to decrypt message');
278
183
  }
279
184
  }
280
185
  if (fullMessage.message) {
@@ -285,33 +190,18 @@ export const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
285
190
  }
286
191
  }
287
192
  catch (err) {
288
- const errorContext = {
289
- key: fullMessage.key,
290
- err,
291
- messageType: tag === 'plaintext' ? 'plaintext' : attrs.type,
292
- sender,
293
- author,
294
- isSessionRecordError: isSessionRecordError(err)
295
- };
296
- logger.error(errorContext, 'failed to decrypt message');
297
- fullMessage.messageStubType = proto.WebMessageInfo.StubType.CIPHERTEXT;
298
- fullMessage.messageStubParameters = [err.message.toString()];
193
+ logger.error({ key: fullMessage.key, err }, 'failed to decrypt message');
194
+ fullMessage.messageStubType = WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT;
195
+ fullMessage.messageStubParameters = [err.message];
299
196
  }
300
197
  }
301
198
  }
302
199
  // if nothing was found to decrypt
303
- if (!decryptables && !fullMessage.key?.isViewOnce) {
304
- fullMessage.messageStubType = proto.WebMessageInfo.StubType.CIPHERTEXT;
305
- fullMessage.messageStubParameters = [NO_MESSAGE_FOUND_ERROR_TEXT];
200
+ if (!decryptables) {
201
+ fullMessage.messageStubType = WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT;
202
+ fullMessage.messageStubParameters = [exports.NO_MESSAGE_FOUND_ERROR_TEXT];
306
203
  }
307
204
  }
308
205
  };
309
206
  };
310
- /**
311
- * Utility function to check if an error is related to missing session record
312
- */
313
- function isSessionRecordError(error) {
314
- const errorMessage = error?.message || error?.toString() || '';
315
- return DECRYPTION_RETRY_CONFIG.sessionRecordErrors.some(errorPattern => errorMessage.includes(errorPattern));
316
- }
317
- //# sourceMappingURL=decode-wa-message.js.map
207
+ exports.decryptMessageNode = decryptMessageNode;