@periskope/baileys 6.7.18-alpha.4 → 6.7.18-alpha.5

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 (75) hide show
  1. package/README.md +1 -1
  2. package/WAProto/GenerateStatics.sh +2 -0
  3. package/WAProto/WAProto.proto +4633 -0
  4. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  5. package/lib/Signal/Group/ciphertext-message.js +15 -0
  6. package/lib/Signal/Group/group-session-builder.d.ts +14 -0
  7. package/lib/Signal/Group/group-session-builder.js +64 -0
  8. package/lib/Signal/Group/group_cipher.d.ts +17 -0
  9. package/lib/Signal/Group/group_cipher.js +96 -0
  10. package/lib/Signal/Group/index.d.ts +11 -0
  11. package/lib/Signal/Group/index.js +57 -0
  12. package/lib/Signal/Group/keyhelper.d.ts +10 -0
  13. package/lib/Signal/Group/keyhelper.js +55 -0
  14. package/lib/Signal/Group/queue-job.d.ts +1 -0
  15. package/lib/Signal/Group/queue-job.js +57 -0
  16. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  17. package/lib/Signal/Group/sender-chain-key.js +34 -0
  18. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  19. package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
  20. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  21. package/lib/Signal/Group/sender-key-message.js +69 -0
  22. package/lib/Signal/Group/sender-key-name.d.ts +17 -0
  23. package/lib/Signal/Group/sender-key-name.js +51 -0
  24. package/lib/Signal/Group/sender-key-record.d.ts +30 -0
  25. package/lib/Signal/Group/sender-key-record.js +53 -0
  26. package/lib/Signal/Group/sender-key-state.d.ts +38 -0
  27. package/lib/Signal/Group/sender-key-state.js +99 -0
  28. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  29. package/{WASignalGroup/sender_message_key.js → lib/Signal/Group/sender-message-key.js} +29 -39
  30. package/lib/Signal/libsignal.js +28 -15
  31. package/lib/Socket/business.d.ts +29 -3
  32. package/lib/Socket/chats.d.ts +7 -5
  33. package/lib/Socket/chats.js +6 -4
  34. package/lib/Socket/groups.d.ts +7 -3
  35. package/lib/Socket/index.d.ts +29 -3
  36. package/lib/Socket/messages-recv.d.ts +29 -3
  37. package/lib/Socket/messages-recv.js +140 -0
  38. package/lib/Socket/messages-send.d.ts +29 -3
  39. package/lib/Socket/messages-send.js +28 -2
  40. package/lib/Socket/mex.d.ts +2 -0
  41. package/lib/Socket/mex.js +46 -0
  42. package/lib/Socket/newsletter.d.ts +139 -0
  43. package/lib/Socket/newsletter.js +183 -0
  44. package/lib/Socket/socket.d.ts +1 -1
  45. package/lib/Socket/socket.js +6 -2
  46. package/lib/Socket/usync.d.ts +1 -1
  47. package/lib/Types/Events.d.ts +26 -0
  48. package/lib/Types/Message.d.ts +8 -2
  49. package/lib/Types/Newsletter.d.ts +134 -0
  50. package/lib/Types/Newsletter.js +33 -0
  51. package/lib/Types/index.d.ts +1 -0
  52. package/lib/Types/index.js +1 -0
  53. package/lib/Utils/decode-wa-message.d.ts +3 -4
  54. package/lib/Utils/decode-wa-message.js +7 -2
  55. package/lib/Utils/generics.d.ts +1 -0
  56. package/lib/Utils/generics.js +4 -0
  57. package/lib/Utils/messages-media.d.ts +9 -1
  58. package/lib/Utils/messages-media.js +63 -28
  59. package/lib/Utils/messages.d.ts +2 -2
  60. package/lib/Utils/messages.js +39 -9
  61. package/package.json +2 -4
  62. package/WASignalGroup/GroupProtocol.js +0 -1697
  63. package/WASignalGroup/ciphertext_message.js +0 -16
  64. package/WASignalGroup/group_cipher.js +0 -120
  65. package/WASignalGroup/group_session_builder.js +0 -46
  66. package/WASignalGroup/index.js +0 -5
  67. package/WASignalGroup/keyhelper.js +0 -21
  68. package/WASignalGroup/protobufs.js +0 -3
  69. package/WASignalGroup/queue_job.js +0 -69
  70. package/WASignalGroup/sender_chain_key.js +0 -50
  71. package/WASignalGroup/sender_key_distribution_message.js +0 -78
  72. package/WASignalGroup/sender_key_message.js +0 -92
  73. package/WASignalGroup/sender_key_name.js +0 -70
  74. package/WASignalGroup/sender_key_record.js +0 -56
  75. package/WASignalGroup/sender_key_state.js +0 -129
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.getHttpStream = exports.getStream = exports.toBuffer = exports.toReadable = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.hkdfInfoKey = void 0;
39
+ exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.getHttpStream = exports.getStream = exports.toBuffer = exports.toReadable = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.getRawMediaUploadData = exports.hkdfInfoKey = void 0;
40
40
  exports.processImage = processImage;
41
41
  exports.getMediaKeys = getMediaKeys;
42
42
  exports.getAudioDuration = getAudioDuration;
@@ -103,6 +103,45 @@ async function processImage(imageUrl) {
103
103
  return null;
104
104
  }
105
105
  }
106
+ const getRawMediaUploadData = async (media, mediaType, logger) => {
107
+ const { stream } = await (0, exports.getStream)(media);
108
+ logger === null || logger === void 0 ? void 0 : logger.debug('got stream for raw upload');
109
+ const hasher = Crypto.createHash('sha256');
110
+ const filePath = (0, path_1.join)((0, os_1.tmpdir)(), mediaType + (0, generics_1.generateMessageIDV2)());
111
+ const fileWriteStream = (0, fs_1.createWriteStream)(filePath);
112
+ let fileLength = 0;
113
+ try {
114
+ for await (const data of stream) {
115
+ fileLength += data.length;
116
+ hasher.update(data);
117
+ if (!fileWriteStream.write(data)) {
118
+ await (0, events_1.once)(fileWriteStream, 'drain');
119
+ }
120
+ }
121
+ fileWriteStream.end();
122
+ await (0, events_1.once)(fileWriteStream, 'finish');
123
+ stream.destroy();
124
+ const fileSha256 = hasher.digest();
125
+ logger === null || logger === void 0 ? void 0 : logger.debug('hashed data for raw upload');
126
+ return {
127
+ filePath: filePath,
128
+ fileSha256,
129
+ fileLength
130
+ };
131
+ }
132
+ catch (error) {
133
+ fileWriteStream.destroy();
134
+ stream.destroy();
135
+ try {
136
+ await fs_1.promises.unlink(filePath);
137
+ }
138
+ catch (_a) {
139
+ //
140
+ }
141
+ throw error;
142
+ }
143
+ };
144
+ exports.getRawMediaUploadData = getRawMediaUploadData;
106
145
  /** generates all the keys required to encrypt/decrypt & sign a media message */
107
146
  async function getMediaKeys(buffer, mediaType) {
108
147
  if (!buffer) {
@@ -169,30 +208,25 @@ const extractImageThumb = async (bufferOrFilePath, width = 32) => {
169
208
  exports.extractImageThumb = extractImageThumb;
170
209
  const encodeBase64EncodedStringForUpload = (b64) => encodeURIComponent(b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, ''));
171
210
  exports.encodeBase64EncodedStringForUpload = encodeBase64EncodedStringForUpload;
172
- const generateProfilePicture = async (mediaUpload) => {
211
+ const generateProfilePicture = async (mediaUpload, dimensions) => {
173
212
  var _a, _b;
174
- let bufferOrFilePath;
213
+ let buffer;
214
+ const { width: w = 640, height: h = 640 } = dimensions || {};
175
215
  if (Buffer.isBuffer(mediaUpload)) {
176
- bufferOrFilePath = mediaUpload;
177
- }
178
- else if ('url' in mediaUpload) {
179
- const imageBuffer = await processImage(mediaUpload.url.toString());
180
- if (imageBuffer) {
181
- bufferOrFilePath = imageBuffer;
182
- }
183
- else {
184
- bufferOrFilePath = mediaUpload.url.toString();
185
- }
216
+ buffer = mediaUpload;
186
217
  }
187
218
  else {
188
- bufferOrFilePath = await (0, exports.toBuffer)(mediaUpload.stream);
219
+ // Use getStream to handle all WAMediaUpload types (Buffer, Stream, URL)
220
+ const { stream } = await (0, exports.getStream)(mediaUpload);
221
+ // Convert the resulting stream to a buffer
222
+ buffer = await (0, exports.toBuffer)(stream);
189
223
  }
190
224
  const lib = await getImageProcessingLibrary();
191
225
  let img;
192
226
  if ('sharp' in lib && typeof ((_a = lib.sharp) === null || _a === void 0 ? void 0 : _a.default) === 'function') {
193
227
  img = lib.sharp
194
- .default(bufferOrFilePath)
195
- .resize(640, 640)
228
+ .default(buffer)
229
+ .resize(w, h)
196
230
  .jpeg({
197
231
  quality: 50
198
232
  })
@@ -200,10 +234,10 @@ const generateProfilePicture = async (mediaUpload) => {
200
234
  }
201
235
  else if ('jimp' in lib && typeof ((_b = lib.jimp) === null || _b === void 0 ? void 0 : _b.read) === 'function') {
202
236
  const { read, MIME_JPEG, RESIZE_BILINEAR } = lib.jimp;
203
- const jimp = await read(bufferOrFilePath);
237
+ const jimp = await read(buffer);
204
238
  const min = Math.min(jimp.getWidth(), jimp.getHeight());
205
239
  const cropped = jimp.crop(0, 0, min, min);
206
- img = cropped.quality(50).resize(640, 640, RESIZE_BILINEAR).getBufferAsync(MIME_JPEG);
240
+ img = cropped.quality(50).resize(w, h, RESIZE_BILINEAR).getBufferAsync(MIME_JPEG);
207
241
  }
208
242
  else {
209
243
  throw new boom_1.Boom('No image processing library available');
@@ -222,20 +256,17 @@ exports.mediaMessageSHA256B64 = mediaMessageSHA256B64;
222
256
  async function getAudioDuration(buffer) {
223
257
  const musicMetadata = await Promise.resolve().then(() => __importStar(require('music-metadata')));
224
258
  let metadata;
259
+ const options = {
260
+ duration: true
261
+ };
225
262
  if (Buffer.isBuffer(buffer)) {
226
- metadata = await musicMetadata.parseBuffer(buffer, undefined, { duration: true });
263
+ metadata = await musicMetadata.parseBuffer(buffer, undefined, options);
227
264
  }
228
265
  else if (typeof buffer === 'string') {
229
- const rStream = (0, fs_1.createReadStream)(buffer);
230
- try {
231
- metadata = await musicMetadata.parseStream(rStream, undefined, { duration: true });
232
- }
233
- finally {
234
- rStream.destroy();
235
- }
266
+ metadata = await musicMetadata.parseFile(buffer, options);
236
267
  }
237
268
  else {
238
- metadata = await musicMetadata.parseStream(buffer, undefined, { duration: true });
269
+ metadata = await musicMetadata.parseStream(buffer, undefined, options);
239
270
  }
240
271
  return metadata.format.duration;
241
272
  }
@@ -436,7 +467,11 @@ const toSmallestChunkSize = (num) => {
436
467
  const getUrlFromDirectPath = (directPath) => `https://${DEF_HOST}${directPath}`;
437
468
  exports.getUrlFromDirectPath = getUrlFromDirectPath;
438
469
  const downloadContentFromMessage = async ({ mediaKey, directPath, url }, type, opts = {}) => {
439
- const downloadUrl = url || (0, exports.getUrlFromDirectPath)(directPath);
470
+ const isValidMediaUrl = url === null || url === void 0 ? void 0 : url.startsWith('https://mmg.whatsapp.net/');
471
+ const downloadUrl = isValidMediaUrl ? url : (0, exports.getUrlFromDirectPath)(directPath);
472
+ if (!downloadUrl) {
473
+ throw new boom_1.Boom('No valid media URL or directPath present in message', { statusCode: 400 });
474
+ }
440
475
  const keys = await getMediaKeys(mediaKey, type);
441
476
  return (0, exports.downloadEncryptedContent)(downloadUrl, keys, opts);
442
477
  };
@@ -1,6 +1,6 @@
1
1
  import { type Transform } from 'stream';
2
2
  import { proto } from '../../WAProto';
3
- import { AnyMediaMessageContent, AnyMessageContent, MediaGenerationOptions, MessageContentGenerationOptions, MessageGenerationOptions, MessageGenerationOptionsFromContent, MessageUserReceipt, WAMessage, WAMessageContent, WAProto } from '../Types';
3
+ import { AnyMediaMessageContent, AnyMessageContent, MessageContentGenerationOptions, MessageGenerationOptions, MessageGenerationOptionsFromContent, MessageUserReceipt, WAMessage, WAMessageContent, WAProto } from '../Types';
4
4
  import { ILogger } from './logger';
5
5
  import { MediaDownloadOptions } from './messages-media';
6
6
  /**
@@ -10,7 +10,7 @@ import { MediaDownloadOptions } from './messages-media';
10
10
  */
11
11
  export declare const extractUrlFromText: (text: string) => string | undefined;
12
12
  export declare const generateLinkPreviewIfRequired: (text: string, getUrlInfo: MessageGenerationOptions["getUrlInfo"], logger: MessageGenerationOptions["logger"]) => Promise<import("../Types").WAUrlInfo | undefined>;
13
- export declare const prepareWAMessageMedia: (message: AnyMediaMessageContent, options: MediaGenerationOptions) => Promise<proto.Message>;
13
+ export declare const prepareWAMessageMedia: (message: AnyMediaMessageContent, options: MessageContentGenerationOptions) => Promise<proto.Message>;
14
14
  export declare const prepareDisappearingMessageSettingContent: (ephemeralExpiration?: number) => proto.Message;
15
15
  /**
16
16
  * Generate forwarded message content like WA does
@@ -82,12 +82,10 @@ const prepareWAMessageMedia = async (message, options) => {
82
82
  media: message[mediaType]
83
83
  };
84
84
  delete uploadData[mediaType];
85
- // check if cacheable + generate cache key
86
85
  const cacheableKey = typeof uploadData.media === 'object' &&
87
86
  'url' in uploadData.media &&
88
87
  !!uploadData.media.url &&
89
88
  !!options.mediaCache &&
90
- // generate the key
91
89
  mediaType + ':' + uploadData.media.url.toString();
92
90
  if (mediaType === 'document' && !uploadData.fileName) {
93
91
  uploadData.fileName = 'file';
@@ -95,7 +93,6 @@ const prepareWAMessageMedia = async (message, options) => {
95
93
  if (!uploadData.mimetype) {
96
94
  uploadData.mimetype = MIMETYPE_MAP[mediaType];
97
95
  }
98
- // check for cache hit
99
96
  if (cacheableKey) {
100
97
  const mediaBuff = options.mediaCache.get(cacheableKey);
101
98
  if (mediaBuff) {
@@ -106,6 +103,37 @@ const prepareWAMessageMedia = async (message, options) => {
106
103
  return obj;
107
104
  }
108
105
  }
106
+ const isNewsletter = !!options.jid && (0, WABinary_1.isJidNewsletter)(options.jid);
107
+ if (isNewsletter) {
108
+ logger === null || logger === void 0 ? void 0 : logger.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
109
+ const { filePath, fileSha256, fileLength } = await (0, messages_media_1.getRawMediaUploadData)(uploadData.media, options.mediaTypeOverride || mediaType, logger);
110
+ const fileSha256B64 = fileSha256.toString('base64');
111
+ const { mediaUrl, directPath } = await options.upload(filePath, {
112
+ fileEncSha256B64: fileSha256B64,
113
+ mediaType: mediaType,
114
+ timeoutMs: options.mediaUploadTimeoutMs
115
+ });
116
+ await fs_1.promises.unlink(filePath);
117
+ const obj = Types_1.WAProto.Message.fromObject({
118
+ [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
119
+ url: mediaUrl,
120
+ directPath,
121
+ fileSha256,
122
+ fileLength,
123
+ ...uploadData,
124
+ media: undefined
125
+ })
126
+ });
127
+ if (uploadData.ptv) {
128
+ obj.ptvMessage = obj.videoMessage;
129
+ delete obj.videoMessage;
130
+ }
131
+ if (cacheableKey) {
132
+ logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
133
+ options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
134
+ }
135
+ return obj;
136
+ }
109
137
  const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
110
138
  const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
111
139
  const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
@@ -116,7 +144,6 @@ const prepareWAMessageMedia = async (message, options) => {
116
144
  saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
117
145
  opts: options.options
118
146
  });
119
- // url safe Base64 encode the SHA256 hash of the body
120
147
  const fileEncSha256B64 = fileEncSha256.toString('base64');
121
148
  const [{ mediaUrl, directPath }] = await Promise.all([
122
149
  (async () => {
@@ -399,12 +426,12 @@ const generateWAMessageContent = async (message, options) => {
399
426
  m.pollCreationMessageV2 = pollCreationMessage;
400
427
  }
401
428
  else {
402
- if (message.poll.selectableCount > 0) {
429
+ if (message.poll.selectableCount === 1) {
403
430
  //poll v3 is for single select polls
404
431
  m.pollCreationMessageV3 = pollCreationMessage;
405
432
  }
406
433
  else {
407
- // poll v3 for multiple choice polls
434
+ // poll for multiple choice polls
408
435
  m.pollCreationMessage = pollCreationMessage;
409
436
  }
410
437
  }
@@ -456,7 +483,7 @@ const generateWAMessageFromContent = (jid, message, options) => {
456
483
  const key = (0, exports.getContentType)(innerMessage);
457
484
  const timestamp = (0, generics_1.unixTimestampSeconds)(options.timestamp);
458
485
  const { quoted, userJid } = options;
459
- if (quoted) {
486
+ if (quoted && !(0, WABinary_1.isJidNewsletter)(jid)) {
460
487
  const participant = quoted.key.fromMe
461
488
  ? userJid
462
489
  : quoted.participant || quoted.key.participant || quoted.key.remoteJid;
@@ -487,7 +514,9 @@ const generateWAMessageFromContent = (jid, message, options) => {
487
514
  // and it's not a protocol message -- delete, toggle disappear message
488
515
  key !== 'protocolMessage' &&
489
516
  // already not converted to disappearing message
490
- key !== 'ephemeralMessage') {
517
+ key !== 'ephemeralMessage' &&
518
+ // newsletters don't support ephemeral messages
519
+ !(0, WABinary_1.isJidNewsletter)(jid)) {
491
520
  innerMessage[key].contextInfo = {
492
521
  ...(innerMessage[key].contextInfo || {}),
493
522
  expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL
@@ -514,7 +543,8 @@ const generateWAMessage = async (jid, content, options) => {
514
543
  var _a;
515
544
  // ensure msg ID is with every log
516
545
  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);
546
+ // Pass jid in the options to generateWAMessageContent
547
+ return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { ...options, jid }), options);
518
548
  };
519
549
  exports.generateWAMessage = generateWAMessage;
520
550
  /** Get the key to access the true type of content */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@periskope/baileys",
3
- "version": "6.7.18-alpha.4",
3
+ "version": "6.7.18-alpha.5",
4
4
  "description": "WhatsApp API", "keywords": [
5
5
  "whatsapp",
6
6
  "automation"
@@ -15,9 +15,7 @@
15
15
  "types": "lib/index.d.ts",
16
16
  "files": [
17
17
  "lib/*",
18
- "WAProto/*.ts",
19
- "WAProto/*.js",
20
- "WASignalGroup/*.js",
18
+ "WAProto/*",
21
19
  "engine-requirements.js"
22
20
  ],
23
21
  "scripts": {