@queenanya/baileys 6.9.5 → 7.0.0

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 (53) hide show
  1. package/README.md +56 -13
  2. package/lib/Defaults/baileys-version.json +1 -1
  3. package/lib/Defaults/index.js +4 -1
  4. package/lib/Socket/business.d.ts +46 -9
  5. package/lib/Socket/chats.d.ts +10 -2
  6. package/lib/Socket/chats.js +40 -1
  7. package/lib/Socket/groups.d.ts +17 -3
  8. package/lib/Socket/groups.js +12 -1
  9. package/lib/Socket/index.d.ts +46 -9
  10. package/lib/Socket/messages-recv.d.ts +45 -9
  11. package/lib/Socket/messages-recv.js +166 -15
  12. package/lib/Socket/messages-send.d.ts +39 -5
  13. package/lib/Socket/messages-send.js +153 -37
  14. package/lib/Socket/newsletter.d.ts +140 -0
  15. package/lib/Socket/newsletter.js +249 -0
  16. package/lib/Socket/registration.d.ts +46 -12
  17. package/lib/Socket/socket.js +4 -3
  18. package/lib/Store/make-in-memory-store.js +5 -1
  19. package/lib/Types/Chat.d.ts +5 -0
  20. package/lib/Types/Events.d.ts +32 -1
  21. package/lib/Types/GroupMetadata.d.ts +1 -1
  22. package/lib/Types/Label.d.ts +11 -0
  23. package/lib/Types/Message.d.ts +39 -27
  24. package/lib/Types/Newsletter.d.ts +79 -0
  25. package/lib/Types/Newsletter.js +18 -0
  26. package/lib/Types/Socket.d.ts +7 -0
  27. package/lib/Types/index.d.ts +9 -0
  28. package/lib/Types/index.js +1 -0
  29. package/lib/Utils/chat-utils.js +16 -0
  30. package/lib/Utils/crypto.d.ts +1 -1
  31. package/lib/Utils/crypto.js +4 -2
  32. package/lib/Utils/decode-wa-message.d.ts +1 -0
  33. package/lib/Utils/decode-wa-message.js +50 -22
  34. package/lib/Utils/generics.d.ts +30 -10
  35. package/lib/Utils/generics.js +82 -10
  36. package/lib/Utils/history.d.ts +4 -0
  37. package/lib/Utils/history.js +3 -0
  38. package/lib/Utils/logger.d.ts +1 -3
  39. package/lib/Utils/messages-media.d.ts +10 -1
  40. package/lib/Utils/messages-media.js +61 -18
  41. package/lib/Utils/messages.js +72 -69
  42. package/lib/Utils/noise-handler.d.ts +1 -1
  43. package/lib/Utils/noise-handler.js +2 -2
  44. package/lib/Utils/process-message.d.ts +3 -2
  45. package/lib/Utils/process-message.js +47 -24
  46. package/lib/Utils/signal.js +21 -16
  47. package/lib/WABinary/decode.d.ts +2 -2
  48. package/lib/WABinary/decode.js +6 -4
  49. package/lib/WABinary/encode.d.ts +1 -2
  50. package/lib/WABinary/encode.js +1 -1
  51. package/lib/WABinary/jid-utils.d.ts +3 -1
  52. package/lib/WABinary/jid-utils.js +4 -1
  53. package/package.json +31 -27
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.bytesToCrockford = exports.trimUndefined = exports.isWABusinessPlatform = exports.getCodeFromWSError = exports.getCallStatusFromNode = exports.getErrorCodeFromStreamError = exports.getStatusFromReceiptType = exports.generateMdTagPrefix = exports.fetchLatestWaWebVersion = exports.fetchLatestBaileysVersion = exports.printQRIfNecessaryListener = exports.bindWaitForConnectionUpdate = exports.bindWaitForEvent = exports.generateMessageID = exports.promiseTimeout = exports.delayCancellable = exports.delay = exports.debouncedTimeout = exports.unixTimestampSeconds = exports.toNumber = exports.encodeBigEndian = exports.generateRegistrationId = exports.encodeWAMessage = exports.unpadRandomMax16 = exports.writeRandomPadMax16 = exports.getKeyAuthor = exports.BufferJSON = exports.Browsers = void 0;
6
+ exports.bytesToCrockford = exports.trimUndefined = exports.isWABusinessPlatform = exports.getCodeFromWSError = exports.getCallStatusFromNode = exports.getErrorCodeFromStreamError = exports.getStatusFromReceiptType = exports.generateMdTagPrefix = exports.fetchLatestWaWebVersion = exports.fetchLatestBaileysVersion2 = exports.fetchLatestBaileysVersion = exports.printQRIfNecessaryListener = exports.bindWaitForConnectionUpdate = exports.bindWaitForEvent = exports.generateMessageID = exports.generateMessageIDV3 = exports.generateMessageIDV2 = exports.promiseTimeout = exports.delayCancellable = exports.delay = exports.debouncedTimeout = exports.unixTimestampSeconds = exports.toNumber = exports.encodeBigEndian = exports.generateRegistrationId = exports.encodeNewsletterMessage = exports.encodeWAMessage = exports.unpadRandomMax16 = exports.writeRandomPadMax16 = exports.getKeyAuthor = exports.BufferJSON = exports.getPlatformId = exports.Browsers = void 0;
7
7
  const boom_1 = require("@hapi/boom");
8
8
  const axios_1 = __importDefault(require("axios"));
9
9
  const crypto_1 = require("crypto");
@@ -12,20 +12,39 @@ const WAProto_1 = require("../../WAProto");
12
12
  const baileys_version_json_1 = require("../Defaults/baileys-version.json");
13
13
  const Types_1 = require("../Types");
14
14
  const WABinary_1 = require("../WABinary");
15
+ /** Added Extra Browsers or Platforms*/
15
16
  const PLATFORM_MAP = {
16
17
  'aix': 'AIX',
17
18
  'darwin': 'Mac OS',
18
19
  'win32': 'Windows',
19
- 'android': 'Android'
20
+ 'android': 'Android',
21
+ 'freebsd': 'FreeBSD',
22
+ 'openbsd': 'OpenBSD',
23
+ 'sunos': 'Solaris'
20
24
  };
25
+ /**
26
+ const COMPANION_PLATFORM_MAP = {
27
+ 'Chrome': '49',
28
+ 'Edge': '50',
29
+ 'Firefox': '51',
30
+ 'Opera': '53',
31
+ 'Safari': '54'
32
+ }
33
+ */
21
34
  exports.Browsers = {
22
- ubuntu: browser => ['Ubuntu', browser, '20.0.04'],
23
- macOS: browser => ['Mac OS', browser, '10.15.7'],
24
- baileys: browser => ['Baileys', browser, '4.0.0'],
25
- windows: browser => ['Windows', browser, '10.0.22621'],
35
+ ubuntu: (browser) => ['Ubuntu', browser, '22.04.4'],
36
+ macOS: (browser) => ['Mac OS', browser, '14.4.1'],
37
+ baileys: (browser) => ['Baileys', browser, '6.5.0'],
38
+ windows: (browser) => ['Windows', browser, '10.0.22631'],
26
39
  /** The appropriate browser based on your OS & release */
27
- appropriate: browser => [PLATFORM_MAP[(0, os_1.platform)()] || 'Ubuntu', browser, (0, os_1.release)()]
40
+ appropriate: (browser) => [PLATFORM_MAP[(0, os_1.platform)()] || 'Ubuntu', browser, (0, os_1.release)()]
28
41
  };
42
+ /** Other Browser Support for Paircode */
43
+ const getPlatformId = (browser) => {
44
+ const platformType = WAProto_1.proto.DeviceProps.PlatformType[browser.toUpperCase()];
45
+ return platformType ? platformType.toString().charCodeAt(0).toString() : '51'; // Firefox
46
+ };
47
+ exports.getPlatformId = getPlatformId;
29
48
  exports.BufferJSON = {
30
49
  replacer: (k, value) => {
31
50
  if (Buffer.isBuffer(value) || value instanceof Uint8Array || (value === null || value === void 0 ? void 0 : value.type) === 'Buffer') {
@@ -66,6 +85,8 @@ const unpadRandomMax16 = (e) => {
66
85
  exports.unpadRandomMax16 = unpadRandomMax16;
67
86
  const encodeWAMessage = (message) => ((0, exports.writeRandomPadMax16)(WAProto_1.proto.Message.encode(message).finish()));
68
87
  exports.encodeWAMessage = encodeWAMessage;
88
+ const encodeNewsletterMessage = (message) => (WAProto_1.proto.Message.encode(message).finish());
89
+ exports.encodeNewsletterMessage = encodeNewsletterMessage;
69
90
  const generateRegistrationId = () => {
70
91
  return Uint16Array.from((0, crypto_1.randomBytes)(2))[0] & 16383;
71
92
  };
@@ -147,8 +168,33 @@ async function promiseTimeout(ms, promise) {
147
168
  return p;
148
169
  }
149
170
  exports.promiseTimeout = promiseTimeout;
171
+ //Useless but still keep this to avoid unexpected errors and bugs
172
+ const generateMessageIDV2 = (userId) => {
173
+ const data = Buffer.alloc(8 + 20 + 16);
174
+ data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)));
175
+ if (userId) {
176
+ const id = (0, WABinary_1.jidDecode)(userId);
177
+ if (id === null || id === void 0 ? void 0 : id.user) {
178
+ data.write(id.user, 8);
179
+ data.write('@c.us', 8 + id.user.length);
180
+ }
181
+ }
182
+ const random = (0, crypto_1.randomBytes)(16);
183
+ random.copy(data, 28);
184
+ const hash = (0, crypto_1.createHash)('sha256').update(data).digest();
185
+ return 'ANYAWEB' + hash.toString('hex').toUpperCase().substring(0, 18);
186
+ };
187
+ exports.generateMessageIDV2 = generateMessageIDV2;
188
+ //Message ID function for ShizoWeb
189
+ //This V3 is RollBack Update to old Message ID
190
+ const generateMessageIDV3 = (userId) => {
191
+ let swebfix = 'ANYAWEB';
192
+ let swebRandom = (0, crypto_1.randomBytes)(5).toString('hex').toUpperCase().substring(0, 10);
193
+ return swebfix + swebRandom;
194
+ };
195
+ exports.generateMessageIDV3 = generateMessageIDV3;
150
196
  // generate a random ID to attach to a message
151
- const generateMessageID = () => 'BAE5' + (0, crypto_1.randomBytes)(6).toString('hex').toUpperCase();
197
+ const generateMessageID = () => 'ANYAWEB' + (0, crypto_1.randomBytes)(10).toString('hex').toUpperCase();
152
198
  exports.generateMessageID = generateMessageID;
153
199
  function bindWaitForEvent(ev, event) {
154
200
  return async (check, timeoutMs) => {
@@ -192,10 +238,36 @@ const printQRIfNecessaryListener = (ev, logger) => {
192
238
  };
193
239
  exports.printQRIfNecessaryListener = printQRIfNecessaryListener;
194
240
  /**
195
- * utility that fetches latest baileys version from the master branch.
241
+ * utility that fetches latest baileys version from the main branch.
196
242
  * Use to ensure your WA connection is always on the latest version
197
243
  */
198
244
  const fetchLatestBaileysVersion = async (options = {}) => {
245
+ try {
246
+ const result = await axios_1.default.get('https://raw.githubusercontent.com/wppconnect-team/wa-version/main/versions.json', {
247
+ ...options,
248
+ responseType: 'json'
249
+ });
250
+ const version = result.data.currentVersion.split('.');
251
+ const version2 = version[2].replace('-alpha', '');
252
+ return {
253
+ version: [+version[0], +version[1], +version2],
254
+ isLatest: true
255
+ };
256
+ }
257
+ catch (error) {
258
+ return {
259
+ version: baileys_version_json_1.version,
260
+ isLatest: false,
261
+ error
262
+ };
263
+ }
264
+ };
265
+ exports.fetchLatestBaileysVersion = fetchLatestBaileysVersion;
266
+ /**
267
+ * utility that fetches latest baileys version from the master branch.
268
+ * Use to ensure your WA connection is always on the latest version
269
+ */
270
+ const fetchLatestBaileysVersion2 = async (options = {}) => {
199
271
  const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/baileys-version.json';
200
272
  try {
201
273
  const result = await axios_1.default.get(URL, {
@@ -215,7 +287,7 @@ const fetchLatestBaileysVersion = async (options = {}) => {
215
287
  };
216
288
  }
217
289
  };
218
- exports.fetchLatestBaileysVersion = fetchLatestBaileysVersion;
290
+ exports.fetchLatestBaileysVersion2 = fetchLatestBaileysVersion2;
219
291
  /**
220
292
  * A utility that fetches the latest web version of whatsapp.
221
293
  * Use to ensure your WA connection is always on the latest version
@@ -6,10 +6,14 @@ export declare const processHistoryMessage: (item: proto.IHistorySync) => {
6
6
  chats: Chat[];
7
7
  contacts: Contact[];
8
8
  messages: proto.IWebMessageInfo[];
9
+ syncType: proto.HistorySync.HistorySyncType;
10
+ progress: number | null | undefined;
9
11
  };
10
12
  export declare const downloadAndProcessHistorySyncNotification: (msg: proto.Message.IHistorySyncNotification, options: AxiosRequestConfig<any>) => Promise<{
11
13
  chats: Chat[];
12
14
  contacts: Contact[];
13
15
  messages: proto.IWebMessageInfo[];
16
+ syncType: proto.HistorySync.HistorySyncType;
17
+ progress: number | null | undefined;
14
18
  }>;
15
19
  export declare const getHistoryMsg: (message: proto.IMessage) => proto.Message.IHistorySyncNotification | null | undefined;
@@ -32,6 +32,7 @@ const processHistoryMessage = (item) => {
32
32
  case WAProto_1.proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP:
33
33
  case WAProto_1.proto.HistorySync.HistorySyncType.RECENT:
34
34
  case WAProto_1.proto.HistorySync.HistorySyncType.FULL:
35
+ case WAProto_1.proto.HistorySync.HistorySyncType.ON_DEMAND:
35
36
  for (const chat of item.conversations) {
36
37
  contacts.push({ id: chat.id, name: chat.name || undefined });
37
38
  const msgs = chat.messages || [];
@@ -74,6 +75,8 @@ const processHistoryMessage = (item) => {
74
75
  chats,
75
76
  contacts,
76
77
  messages,
78
+ syncType: item.syncType,
79
+ progress: item.progress,
77
80
  };
78
81
  };
79
82
  exports.processHistoryMessage = processHistoryMessage;
@@ -1,4 +1,2 @@
1
- declare const _default: import("pino").Logger<{
2
- timestamp: () => string;
3
- }>;
1
+ declare const _default: import("pino").Logger<never>;
4
2
  export default _default;
@@ -63,6 +63,15 @@ type EncryptedStreamOptions = {
63
63
  logger?: Logger;
64
64
  opts?: AxiosRequestConfig;
65
65
  };
66
+ export declare const prepareStream: (media: WAMediaUpload, mediaType: MediaType, { logger, saveOriginalFileIfRequired, opts }?: EncryptedStreamOptions) => Promise<{
67
+ mediaKey: undefined;
68
+ encWriteStream: Buffer;
69
+ fileLength: number;
70
+ fileSha256: Buffer;
71
+ fileEncSha256: undefined;
72
+ bodyPath: string | undefined;
73
+ didSaveToTmpPath: boolean;
74
+ }>;
66
75
  export declare const encryptedStream: (media: WAMediaUpload, mediaType: MediaType, { logger, saveOriginalFileIfRequired, opts }?: EncryptedStreamOptions) => Promise<{
67
76
  mediaKey: Buffer;
68
77
  encWriteStream: Readable;
@@ -92,7 +101,7 @@ export declare const getWAUploadToServer: ({ customUploadHosts, fetchAgent, logg
92
101
  */
93
102
  export declare const encryptMediaRetryRequest: (key: proto.IMessageKey, mediaKey: Buffer | Uint8Array, meId: string) => BinaryNode;
94
103
  export declare const decodeMediaRetryNode: (node: BinaryNode) => {
95
- key: proto.IMessageKey;
104
+ key: import("../Types").WAMessageKey;
96
105
  media?: {
97
106
  ciphertext: Uint8Array;
98
107
  iv: Uint8Array;
@@ -22,9 +22,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.extensionForMediaMessage = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.getHttpStream = exports.generateThumbnail = exports.getStream = exports.toBuffer = exports.toReadable = exports.getAudioWaveform = exports.getAudioDuration = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.getMediaKeys = exports.hkdfInfoKey = void 0;
29
+ exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.extensionForMediaMessage = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.prepareStream = exports.getHttpStream = exports.generateThumbnail = exports.getStream = exports.toBuffer = exports.toReadable = exports.getAudioWaveform = exports.getAudioDuration = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.getMediaKeys = exports.hkdfInfoKey = void 0;
27
30
  const boom_1 = require("@hapi/boom");
31
+ const axios_1 = __importDefault(require("axios"));
28
32
  const child_process_1 = require("child_process");
29
33
  const Crypto = __importStar(require("crypto"));
30
34
  const events_1 = require("events");
@@ -313,11 +317,54 @@ async function generateThumbnail(file, mediaType, options) {
313
317
  }
314
318
  exports.generateThumbnail = generateThumbnail;
315
319
  const getHttpStream = async (url, options = {}) => {
316
- const { default: axios } = await import('axios');
317
- const fetched = await axios.get(url.toString(), { ...options, responseType: 'stream' });
320
+ const fetched = await axios_1.default.get(url.toString(), { ...options, responseType: 'stream' });
318
321
  return fetched.data;
319
322
  };
320
323
  exports.getHttpStream = getHttpStream;
324
+ const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
325
+ const { stream, type } = await (0, exports.getStream)(media, opts);
326
+ logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
327
+ let bodyPath;
328
+ let didSaveToTmpPath = false;
329
+ try {
330
+ const buffer = await (0, exports.toBuffer)(stream);
331
+ if (type === 'file') {
332
+ bodyPath = media.url;
333
+ }
334
+ else if (saveOriginalFileIfRequired) {
335
+ bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageID)());
336
+ (0, fs_1.writeFileSync)(bodyPath, buffer);
337
+ didSaveToTmpPath = true;
338
+ }
339
+ const fileLength = buffer.length;
340
+ const fileSha256 = Crypto.createHash('sha256').update(buffer).digest();
341
+ stream === null || stream === void 0 ? void 0 : stream.destroy();
342
+ logger === null || logger === void 0 ? void 0 : logger.debug('prepare stream data successfully');
343
+ return {
344
+ mediaKey: undefined,
345
+ encWriteStream: buffer,
346
+ fileLength,
347
+ fileSha256,
348
+ fileEncSha256: undefined,
349
+ bodyPath,
350
+ didSaveToTmpPath
351
+ };
352
+ }
353
+ catch (error) {
354
+ // destroy all streams with error
355
+ stream.destroy();
356
+ if (didSaveToTmpPath) {
357
+ try {
358
+ await fs_1.promises.unlink(bodyPath);
359
+ }
360
+ catch (err) {
361
+ logger === null || logger === void 0 ? void 0 : logger.error({ err }, 'failed to save to tmp path');
362
+ }
363
+ }
364
+ throw error;
365
+ }
366
+ };
367
+ exports.prepareStream = prepareStream;
321
368
  const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
322
369
  const { stream, type } = await (0, exports.getStream)(media, opts);
323
370
  logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
@@ -523,29 +570,24 @@ function extensionForMediaMessage(message) {
523
570
  }
524
571
  exports.extensionForMediaMessage = extensionForMediaMessage;
525
572
  const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
526
- return async (stream, { mediaType, fileEncSha256B64, timeoutMs }) => {
573
+ return async (stream, { mediaType, fileEncSha256B64, newsletter, timeoutMs }) => {
527
574
  var _a, _b;
528
- const { default: axios } = await import('axios');
529
575
  // send a query JSON to obtain the url & auth token to upload our media
530
576
  let uploadInfo = await refreshMediaConn(false);
531
577
  let urls;
532
578
  const hosts = [...customUploadHosts, ...uploadInfo.hosts];
533
- const chunks = [];
534
- for await (const chunk of stream) {
535
- chunks.push(chunk);
536
- }
537
- const reqBody = Buffer.concat(chunks);
538
579
  fileEncSha256B64 = (0, exports.encodeBase64EncodedStringForUpload)(fileEncSha256B64);
539
- for (const { hostname, maxContentLengthBytes } of hosts) {
580
+ let media = Defaults_1.MEDIA_PATH_MAP[mediaType];
581
+ if (newsletter) {
582
+ media = media === null || media === void 0 ? void 0 : media.replace('/mms/', '/newsletter/newsletter-');
583
+ }
584
+ for (const { hostname } of hosts) {
540
585
  logger.debug(`uploading to "${hostname}"`);
541
586
  const auth = encodeURIComponent(uploadInfo.auth); // the auth token
542
- const url = `https://${hostname}${Defaults_1.MEDIA_PATH_MAP[mediaType]}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
587
+ const url = `https://${hostname}${media}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
543
588
  let result;
544
589
  try {
545
- if (maxContentLengthBytes && reqBody.length > maxContentLengthBytes) {
546
- throw new boom_1.Boom(`Body too large for "${hostname}"`, { statusCode: 413 });
547
- }
548
- const body = await axios.post(url, reqBody, {
590
+ const body = await axios_1.default.post(url, stream, {
549
591
  ...options,
550
592
  headers: {
551
593
  ...options.headers || {},
@@ -562,7 +604,8 @@ const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options },
562
604
  if ((result === null || result === void 0 ? void 0 : result.url) || (result === null || result === void 0 ? void 0 : result.directPath)) {
563
605
  urls = {
564
606
  mediaUrl: result.url,
565
- directPath: result.direct_path
607
+ directPath: result.direct_path,
608
+ handle: result.handle
566
609
  };
567
610
  break;
568
611
  }
@@ -572,7 +615,7 @@ const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options },
572
615
  }
573
616
  }
574
617
  catch (error) {
575
- if (axios.isAxiosError(error)) {
618
+ if (axios_1.default.isAxiosError(error)) {
576
619
  result = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data;
577
620
  }
578
621
  const isLast = hostname === ((_b = hosts[uploadInfo.hosts.length - 1]) === null || _b === void 0 ? void 0 : _b.hostname);
@@ -30,7 +30,6 @@ const MessageTypeProto = {
30
30
  'sticker': Types_1.WAProto.Message.StickerMessage,
31
31
  'document': Types_1.WAProto.Message.DocumentMessage,
32
32
  };
33
- const ButtonType = WAProto_1.proto.Message.ButtonsMessage.HeaderType;
34
33
  /**
35
34
  * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
36
35
  * @param text eg. hello https://google.com
@@ -111,14 +110,14 @@ const prepareWAMessageMedia = async (message, options) => {
111
110
  const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
112
111
  const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
113
112
  const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
114
- const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath } = await (0, messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
113
+ const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
115
114
  logger,
116
115
  saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
117
116
  opts: options.options
118
117
  });
119
118
  // url safe Base64 encode the SHA256 hash of the body
120
- const fileEncSha256B64 = fileEncSha256.toString('base64');
121
- const [{ mediaUrl, directPath }] = await Promise.all([
119
+ const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
120
+ const [{ mediaUrl, directPath, handle }] = await Promise.all([
122
121
  (async () => {
123
122
  const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
124
123
  logger === null || logger === void 0 ? void 0 : logger.debug({ mediaType, cacheableKey }, 'uploaded media');
@@ -159,7 +158,9 @@ const prepareWAMessageMedia = async (message, options) => {
159
158
  })(),
160
159
  ])
161
160
  .finally(async () => {
162
- encWriteStream.destroy();
161
+ if (!Buffer.isBuffer(encWriteStream)) {
162
+ encWriteStream.destroy();
163
+ }
163
164
  // remove tmp files
164
165
  if (didSaveToTmpPath && bodyPath) {
165
166
  await fs_1.promises.unlink(bodyPath);
@@ -168,13 +169,13 @@ const prepareWAMessageMedia = async (message, options) => {
168
169
  });
169
170
  const obj = Types_1.WAProto.Message.fromObject({
170
171
  [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
171
- url: mediaUrl,
172
+ url: handle ? undefined : mediaUrl,
172
173
  directPath,
173
- mediaKey,
174
- fileEncSha256,
174
+ mediaKey: mediaKey,
175
+ fileEncSha256: fileEncSha256,
175
176
  fileSha256,
176
177
  fileLength,
177
- mediaKeyTimestamp: (0, generics_1.unixTimestampSeconds)(),
178
+ mediaKeyTimestamp: handle ? undefined : (0, generics_1.unixTimestampSeconds)(),
178
179
  ...uploadData,
179
180
  media: undefined
180
181
  })
@@ -238,7 +239,7 @@ const generateForwardMessageContent = (message, forceForward) => {
238
239
  exports.generateForwardMessageContent = generateForwardMessageContent;
239
240
  const generateWAMessageContent = async (message, options) => {
240
241
  var _a;
241
- var _b;
242
+ var _b, _c;
242
243
  let m = {};
243
244
  if ('text' in message) {
244
245
  const extContent = { text: message.text };
@@ -308,6 +309,41 @@ const generateWAMessageContent = async (message, options) => {
308
309
  message.disappearingMessagesInChat;
309
310
  m = (0, exports.prepareDisappearingMessageSettingContent)(exp);
310
311
  }
312
+ else if ('groupInvite' in message) {
313
+ m.groupInviteMessage = {};
314
+ m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode;
315
+ m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration;
316
+ m.groupInviteMessage.caption = message.groupInvite.text;
317
+ m.groupInviteMessage.groupJid = message.groupInvite.jid;
318
+ m.groupInviteMessage.groupName = message.groupInvite.subject;
319
+ //TODO: use built-in interface and get disappearing mode info etc.
320
+ //TODO: cache / use store!?
321
+ if (options.getProfilePicUrl) {
322
+ const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
323
+ if (pfpUrl) {
324
+ const resp = await axios_1.default.get(pfpUrl, { responseType: 'arraybuffer' });
325
+ if (resp.status === 200) {
326
+ m.groupInviteMessage.jpegThumbnail = resp.data;
327
+ }
328
+ }
329
+ }
330
+ }
331
+ else if ('pin' in message) {
332
+ m.pinInChatMessage = {};
333
+ m.messageContextInfo = {};
334
+ m.pinInChatMessage.key = message.pin;
335
+ m.pinInChatMessage.type = 1;
336
+ m.pinInChatMessage.senderTimestampMs = Date.now();
337
+ m.messageContextInfo.messageAddOnDurationInSecs = message.time || 86400;
338
+ }
339
+ else if ('unpin' in message) {
340
+ m.pinInChatMessage = {};
341
+ m.messageContextInfo = {};
342
+ m.pinInChatMessage.key = message.unpin;
343
+ m.pinInChatMessage.type = 2;
344
+ m.pinInChatMessage.senderTimestampMs = Date.now();
345
+ m.messageContextInfo.messageAddOnDurationInSecs = 0;
346
+ }
311
347
  else if ('buttonReply' in message) {
312
348
  switch (message.type) {
313
349
  case 'template':
@@ -326,6 +362,10 @@ const generateWAMessageContent = async (message, options) => {
326
362
  break;
327
363
  }
328
364
  }
365
+ else if ('ptv' in message && message.ptv) {
366
+ const { videoMessage } = await (0, exports.prepareWAMessageMedia)({ video: message.video }, options);
367
+ m.ptvMessage = videoMessage;
368
+ }
329
369
  else if ('product' in message) {
330
370
  const { imageMessage } = await (0, exports.prepareWAMessageMedia)({ image: message.product.productImage }, options);
331
371
  m.productMessage = Types_1.WAProto.Message.ProductMessage.fromObject({
@@ -341,6 +381,7 @@ const generateWAMessageContent = async (message, options) => {
341
381
  }
342
382
  else if ('poll' in message) {
343
383
  (_b = message.poll).selectableCount || (_b.selectableCount = 0);
384
+ (_c = message.poll).toAnnouncementGroup || (_c.toAnnouncementGroup = false);
344
385
  if (!Array.isArray(message.poll.values)) {
345
386
  throw new boom_1.Boom('Invalid poll values', { statusCode: 400 });
346
387
  }
@@ -352,11 +393,25 @@ const generateWAMessageContent = async (message, options) => {
352
393
  // encKey
353
394
  messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32),
354
395
  };
355
- m.pollCreationMessage = {
396
+ const pollCreationMessage = {
356
397
  name: message.poll.name,
357
398
  selectableOptionsCount: message.poll.selectableCount,
358
399
  options: message.poll.values.map(optionName => ({ optionName })),
359
400
  };
401
+ if (message.poll.toAnnouncementGroup) {
402
+ // poll v2 is for community announcement groups (single select and multiple)
403
+ m.pollCreationMessageV2 = pollCreationMessage;
404
+ }
405
+ else {
406
+ if (message.poll.selectableCount > 0) {
407
+ //poll v3 is for single select polls
408
+ m.pollCreationMessageV3 = pollCreationMessage;
409
+ }
410
+ else {
411
+ // poll v3 for multiple choice polls
412
+ m.pollCreationMessage = pollCreationMessage;
413
+ }
414
+ }
360
415
  }
361
416
  else if ('sharePhoneNumber' in message) {
362
417
  m.protocolMessage = {
@@ -369,61 +424,6 @@ const generateWAMessageContent = async (message, options) => {
369
424
  else {
370
425
  m = await (0, exports.prepareWAMessageMedia)(message, options);
371
426
  }
372
- if ('buttons' in message && !!message.buttons) {
373
- const buttonsMessage = {
374
- buttons: message.buttons.map(b => ({ ...b, type: WAProto_1.proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
375
- };
376
- if ('text' in message) {
377
- buttonsMessage.contentText = message.text;
378
- buttonsMessage.headerType = ButtonType.EMPTY;
379
- }
380
- else {
381
- if ('caption' in message) {
382
- buttonsMessage.contentText = message.caption;
383
- }
384
- const type = Object.keys(m)[0].replace('Message', '').toUpperCase();
385
- buttonsMessage.headerType = ButtonType[type];
386
- Object.assign(buttonsMessage, m);
387
- }
388
- if ('footer' in message && !!message.footer) {
389
- buttonsMessage.footerText = message.footer;
390
- }
391
- m = { buttonsMessage };
392
- }
393
- else if ('templateButtons' in message && !!message.templateButtons) {
394
- const msg = {
395
- hydratedButtons: message.templateButtons
396
- };
397
- if ('text' in message) {
398
- msg.hydratedContentText = message.text;
399
- }
400
- else {
401
- if ('caption' in message) {
402
- msg.hydratedContentText = message.caption;
403
- }
404
- Object.assign(msg, m);
405
- }
406
- if ('footer' in message && !!message.footer) {
407
- msg.hydratedFooterText = message.footer;
408
- }
409
- m = {
410
- templateMessage: {
411
- fourRowTemplate: msg,
412
- hydratedTemplate: msg
413
- }
414
- };
415
- }
416
- if ('sections' in message && !!message.sections) {
417
- const listMessage = {
418
- sections: message.sections,
419
- buttonText: message.buttonText,
420
- title: message.title,
421
- footerText: message.footer,
422
- description: message.text,
423
- listType: WAProto_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
424
- };
425
- m = { listMessage };
426
- }
427
427
  if ('viewOnce' in message && !!message.viewOnce) {
428
428
  m = { viewOnceMessage: { message: m } };
429
429
  }
@@ -460,7 +460,8 @@ const generateWAMessageFromContent = (jid, message, options) => {
460
460
  const key = (0, exports.getContentType)(innerMessage);
461
461
  const timestamp = (0, generics_1.unixTimestampSeconds)(options.timestamp);
462
462
  const { quoted, userJid } = options;
463
- if (quoted) {
463
+ // only set quoted if isn't a newsletter message
464
+ if (quoted && !(0, WABinary_1.isJidNewsletter)(jid)) {
464
465
  const participant = quoted.key.fromMe ? userJid : (quoted.participant || quoted.key.participant || quoted.key.remoteJid);
465
466
  let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message);
466
467
  const msgType = (0, exports.getContentType)(quotedMsg);
@@ -487,7 +488,9 @@ const generateWAMessageFromContent = (jid, message, options) => {
487
488
  // and it's not a protocol message -- delete, toggle disappear message
488
489
  key !== 'protocolMessage' &&
489
490
  // already not converted to disappearing message
490
- key !== 'ephemeralMessage') {
491
+ key !== 'ephemeralMessage' &&
492
+ // newsletter not accept disappearing messages
493
+ !(0, WABinary_1.isJidNewsletter)(jid)) {
491
494
  innerMessage[key].contextInfo = {
492
495
  ...(innerMessage[key].contextInfo || {}),
493
496
  expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL,
@@ -514,7 +517,7 @@ const generateWAMessage = async (jid, content, options) => {
514
517
  var _a;
515
518
  // ensure msg ID is with every log
516
519
  options.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) === null || _a === void 0 ? void 0 : _a.child({ msgId: options.messageId });
517
- return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, options), options);
520
+ return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { newsletter: (0, WABinary_1.isJidNewsletter)(jid), ...options }), options);
518
521
  };
519
522
  exports.generateWAMessage = generateWAMessage;
520
523
  /** Get the key to access the true type of content */
@@ -17,5 +17,5 @@ export declare const makeNoiseHandler: ({ keyPair: { private: privateKey, public
17
17
  finishInit: () => void;
18
18
  processHandshake: ({ serverHello }: proto.HandshakeMessage, noiseKey: KeyPair) => Buffer;
19
19
  encodeFrame: (data: Buffer | Uint8Array) => Buffer;
20
- decodeFrame: (newData: Buffer | Uint8Array, onFrame: (buff: Uint8Array | BinaryNode) => void) => void;
20
+ decodeFrame: (newData: Buffer | Uint8Array, onFrame: (buff: Uint8Array | BinaryNode) => void) => Promise<void>;
21
21
  };
@@ -125,7 +125,7 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
125
125
  frame.set(data, introSize + 3);
126
126
  return frame;
127
127
  },
128
- decodeFrame: (newData, onFrame) => {
128
+ decodeFrame: async (newData, onFrame) => {
129
129
  var _a;
130
130
  // the binary protocol uses its own framing mechanism
131
131
  // on top of the WS frames
@@ -143,7 +143,7 @@ const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey },
143
143
  inBytes = inBytes.slice(size + 3);
144
144
  if (isFinished) {
145
145
  const result = decrypt(frame);
146
- frame = (0, WABinary_1.decodeBinaryNode)(result);
146
+ frame = await (0, WABinary_1.decodeBinaryNode)(result);
147
147
  }
148
148
  logger.trace({ msg: (_a = frame === null || frame === void 0 ? void 0 : frame.attrs) === null || _a === void 0 ? void 0 : _a.id }, 'recv frame');
149
149
  onFrame(frame);
@@ -1,9 +1,10 @@
1
1
  import { AxiosRequestConfig } from 'axios';
2
2
  import type { Logger } from 'pino';
3
3
  import { proto } from '../../WAProto';
4
- import { AuthenticationCreds, BaileysEventEmitter, SignalKeyStoreWithTransaction, SocketConfig } from '../Types';
4
+ import { AuthenticationCreds, BaileysEventEmitter, CacheStore, SignalKeyStoreWithTransaction, SocketConfig } from '../Types';
5
5
  type ProcessMessageContext = {
6
6
  shouldProcessHistoryMsg: boolean;
7
+ placeholderResendCache?: CacheStore;
7
8
  creds: AuthenticationCreds;
8
9
  keyStore: SignalKeyStoreWithTransaction;
9
10
  ev: BaileysEventEmitter;
@@ -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;