@fer2809fl/baileys 7.0.1 → 7.0.2

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 (273) hide show
  1. package/README.md +259 -595
  2. package/WAProto/WAProto.proto +916 -360
  3. package/WAProto/fix-imports.js +18 -22
  4. package/WAProto/index.d.ts +15471 -8638
  5. package/WAProto/index.js +80576 -45941
  6. package/lib/Defaults/index.d.ts +14 -18
  7. package/lib/Defaults/index.d.ts.map +1 -1
  8. package/lib/Defaults/index.js +110 -115
  9. package/lib/Defaults/index.js.map +1 -1
  10. package/lib/Signal/Group/group_cipher.js.map +1 -1
  11. package/lib/Signal/Group/keyhelper.d.ts.map +1 -1
  12. package/lib/Signal/Group/keyhelper.js.map +1 -1
  13. package/lib/Signal/Group/sender-chain-key.js.map +1 -1
  14. package/lib/Signal/Group/sender-key-message.js.map +1 -1
  15. package/lib/Signal/Group/sender-message-key.js.map +1 -1
  16. package/lib/Signal/libsignal.d.ts.map +1 -1
  17. package/lib/Signal/libsignal.js +17 -45
  18. package/lib/Signal/libsignal.js.map +1 -1
  19. package/lib/Signal/lid-mapping.d.ts +0 -4
  20. package/lib/Signal/lid-mapping.d.ts.map +1 -1
  21. package/lib/Signal/lid-mapping.js +0 -6
  22. package/lib/Signal/lid-mapping.js.map +1 -1
  23. package/lib/Socket/business.d.ts +532 -280
  24. package/lib/Socket/business.d.ts.map +1 -1
  25. package/lib/Socket/business.js +401 -358
  26. package/lib/Socket/chats.d.ts +2 -22
  27. package/lib/Socket/chats.d.ts.map +1 -1
  28. package/lib/Socket/chats.js +43 -314
  29. package/lib/Socket/chats.js.map +1 -1
  30. package/lib/Socket/communities.d.ts +641 -336
  31. package/lib/Socket/communities.d.ts.map +1 -1
  32. package/lib/Socket/communities.js +3 -6
  33. package/lib/Socket/communities.js.map +1 -1
  34. package/lib/Socket/dugong.d.ts +130 -0
  35. package/lib/Socket/dugong.d.ts.map +1 -0
  36. package/lib/Socket/dugong.js +772 -0
  37. package/lib/Socket/dugong.js.map +1 -0
  38. package/lib/Socket/groups.d.ts +2 -23
  39. package/lib/Socket/groups.d.ts.map +1 -1
  40. package/lib/Socket/groups.js +8 -171
  41. package/lib/Socket/groups.js.map +1 -1
  42. package/lib/Socket/index.d.ts +631 -322
  43. package/lib/Socket/index.d.ts.map +1 -1
  44. package/lib/Socket/index.js +12 -9
  45. package/lib/Socket/index.js.map +1 -1
  46. package/lib/Socket/messages-recv.d.ts +52 -84
  47. package/lib/Socket/messages-recv.d.ts.map +1 -1
  48. package/lib/Socket/messages-recv.js +185 -686
  49. package/lib/Socket/messages-recv.js.map +1 -1
  50. package/lib/Socket/messages-send.d.ts +643 -262
  51. package/lib/Socket/messages-send.d.ts.map +1 -1
  52. package/lib/Socket/messages-send.js +1559 -1359
  53. package/lib/Socket/messages-send.js.map +1 -1
  54. package/lib/Socket/mex.d.ts +0 -1
  55. package/lib/Socket/mex.d.ts.map +1 -1
  56. package/lib/Socket/mex.js +8 -22
  57. package/lib/Socket/mex.js.map +1 -1
  58. package/lib/Socket/native-buttons.js +231 -0
  59. package/lib/Socket/newsletter.d.ts +27 -42
  60. package/lib/Socket/newsletter.d.ts.map +1 -1
  61. package/lib/Socket/newsletter.js +439 -402
  62. package/lib/Socket/newsletter.js.map +1 -1
  63. package/lib/Socket/socket.d.ts +2 -6
  64. package/lib/Socket/socket.d.ts.map +1 -1
  65. package/lib/Socket/socket.js +26 -62
  66. package/lib/Socket/socket.js.map +1 -1
  67. package/lib/Types/Auth.d.ts +0 -1
  68. package/lib/Types/Auth.d.ts.map +1 -1
  69. package/lib/Types/Bussines.d.ts +34 -22
  70. package/lib/Types/Call.d.ts +1 -1
  71. package/lib/Types/Call.d.ts.map +1 -1
  72. package/lib/Types/Chat.d.ts +0 -1
  73. package/lib/Types/Chat.d.ts.map +1 -1
  74. package/lib/Types/Contact.d.ts +0 -2
  75. package/lib/Types/Contact.d.ts.map +1 -1
  76. package/lib/Types/Events.d.ts +1 -20
  77. package/lib/Types/Events.d.ts.map +1 -1
  78. package/lib/Types/GroupMetadata.d.ts +1 -4
  79. package/lib/Types/GroupMetadata.d.ts.map +1 -1
  80. package/lib/Types/Message.d.ts +348 -354
  81. package/lib/Types/Message.d.ts.map +1 -1
  82. package/lib/Types/Message.js +0 -4
  83. package/lib/Types/Message.js.map +1 -1
  84. package/lib/Types/{Mex.d.ts → Newsletter.d.ts} +7 -26
  85. package/lib/Types/Newsletter.d.ts.map +1 -0
  86. package/lib/Types/{Mex.js → Newsletter.js} +3 -11
  87. package/lib/Types/Newsletter.js.map +1 -0
  88. package/lib/Types/Signal.d.ts +1 -12
  89. package/lib/Types/Signal.d.ts.map +1 -1
  90. package/lib/Types/Socket.d.ts +148 -135
  91. package/lib/Types/Socket.d.ts.map +1 -1
  92. package/lib/Types/Socket.js.map +1 -1
  93. package/lib/Types/State.d.ts +0 -65
  94. package/lib/Types/State.d.ts.map +1 -1
  95. package/lib/Types/State.js +0 -43
  96. package/lib/Types/State.js.map +1 -1
  97. package/lib/Types/index.d.ts +52 -52
  98. package/lib/Types/index.d.ts.map +1 -1
  99. package/lib/Types/index.js +30 -23
  100. package/lib/Types/index.js.map +1 -1
  101. package/lib/Utils/auth-utils.d.ts +0 -5
  102. package/lib/Utils/auth-utils.d.ts.map +1 -1
  103. package/lib/Utils/auth-utils.js +0 -12
  104. package/lib/Utils/auth-utils.js.map +1 -1
  105. package/lib/Utils/browser-utils.d.ts.map +1 -1
  106. package/lib/Utils/browser-utils.js +0 -1
  107. package/lib/Utils/browser-utils.js.map +1 -1
  108. package/lib/Utils/chat-utils.d.ts +4 -34
  109. package/lib/Utils/chat-utils.d.ts.map +1 -1
  110. package/lib/Utils/chat-utils.js +20 -80
  111. package/lib/Utils/chat-utils.js.map +1 -1
  112. package/lib/Utils/crypto.d.ts +12 -12
  113. package/lib/Utils/crypto.d.ts.map +1 -1
  114. package/lib/Utils/crypto.js.map +1 -1
  115. package/lib/Utils/decode-wa-message.d.ts +0 -18
  116. package/lib/Utils/decode-wa-message.d.ts.map +1 -1
  117. package/lib/Utils/decode-wa-message.js +0 -34
  118. package/lib/Utils/decode-wa-message.js.map +1 -1
  119. package/lib/Utils/event-buffer.d.ts +0 -2
  120. package/lib/Utils/event-buffer.d.ts.map +1 -1
  121. package/lib/Utils/event-buffer.js +1 -49
  122. package/lib/Utils/event-buffer.js.map +1 -1
  123. package/lib/Utils/generics.d.ts +2 -3
  124. package/lib/Utils/generics.d.ts.map +1 -1
  125. package/lib/Utils/generics.js +1 -10
  126. package/lib/Utils/generics.js.map +1 -1
  127. package/lib/Utils/history.d.ts +0 -2
  128. package/lib/Utils/history.d.ts.map +1 -1
  129. package/lib/Utils/history.js +9 -12
  130. package/lib/Utils/history.js.map +1 -1
  131. package/lib/Utils/identity-change-handler.d.ts +0 -7
  132. package/lib/Utils/identity-change-handler.d.ts.map +1 -1
  133. package/lib/Utils/identity-change-handler.js +0 -1
  134. package/lib/Utils/identity-change-handler.js.map +1 -1
  135. package/lib/Utils/index.d.ts +23 -30
  136. package/lib/Utils/index.d.ts.map +1 -1
  137. package/lib/Utils/index.js +2 -9
  138. package/lib/Utils/index.js.map +1 -1
  139. package/lib/Utils/link-preview.js +2 -2
  140. package/lib/Utils/link-preview.js.map +1 -1
  141. package/lib/Utils/message-retry-manager.d.ts +0 -5
  142. package/lib/Utils/message-retry-manager.d.ts.map +1 -1
  143. package/lib/Utils/message-retry-manager.js +0 -40
  144. package/lib/Utils/message-retry-manager.js.map +1 -1
  145. package/lib/Utils/messages-media.d.ts +13 -45
  146. package/lib/Utils/messages-media.d.ts.map +1 -1
  147. package/lib/Utils/messages-media.js +98 -293
  148. package/lib/Utils/messages-media.js.map +1 -1
  149. package/lib/Utils/messages.d.ts +3 -16
  150. package/lib/Utils/messages.d.ts.map +1 -1
  151. package/lib/Utils/messages.js +1123 -1219
  152. package/lib/Utils/messages.js.map +1 -1
  153. package/lib/Utils/noise-handler.d.ts +1 -1
  154. package/lib/Utils/process-message.d.ts.map +1 -1
  155. package/lib/Utils/process-message.js +1 -103
  156. package/lib/Utils/process-message.js.map +1 -1
  157. package/lib/Utils/rich-messages.d.ts +277 -0
  158. package/lib/Utils/rich-messages.d.ts.map +1 -0
  159. package/lib/Utils/rich-messages.js +1144 -0
  160. package/lib/Utils/rich-messages.js.map +1 -0
  161. package/lib/Utils/signal.d.ts +0 -13
  162. package/lib/Utils/signal.d.ts.map +1 -1
  163. package/lib/Utils/signal.js +0 -42
  164. package/lib/Utils/signal.js.map +1 -1
  165. package/lib/Utils/sticker-pack.d.ts +10 -0
  166. package/lib/Utils/sticker-pack.js +111 -0
  167. package/lib/Utils/sync-action-utils.d.ts.map +1 -1
  168. package/lib/Utils/sync-action-utils.js +0 -1
  169. package/lib/Utils/sync-action-utils.js.map +1 -1
  170. package/lib/Utils/tc-token-utils.d.ts +1 -26
  171. package/lib/Utils/tc-token-utils.d.ts.map +1 -1
  172. package/lib/Utils/tc-token-utils.js +5 -151
  173. package/lib/Utils/tc-token-utils.js.map +1 -1
  174. package/lib/Utils/validate-connection.d.ts +0 -1
  175. package/lib/Utils/validate-connection.d.ts.map +1 -1
  176. package/lib/Utils/validate-connection.js +3 -13
  177. package/lib/Utils/validate-connection.js.map +1 -1
  178. package/lib/WABinary/decode.d.ts +1 -1
  179. package/lib/WABinary/decode.d.ts.map +1 -1
  180. package/lib/WABinary/generic-utils.d.ts +3 -1
  181. package/lib/WABinary/generic-utils.d.ts.map +1 -1
  182. package/lib/WABinary/generic-utils.js +78 -0
  183. package/lib/WABinary/generic-utils.js.map +1 -1
  184. package/lib/WABinary/jid-utils.d.ts +0 -11
  185. package/lib/WABinary/jid-utils.d.ts.map +1 -1
  186. package/lib/WABinary/jid-utils.js +0 -33
  187. package/lib/WABinary/jid-utils.js.map +1 -1
  188. package/lib/WAM/encode.d.ts +1 -1
  189. package/lib/WAM/encode.d.ts.map +1 -1
  190. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -1
  191. package/lib/WAUSync/Protocols/USyncContactProtocol.js +3 -26
  192. package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -1
  193. package/lib/WAUSync/Protocols/index.d.ts +0 -1
  194. package/lib/WAUSync/Protocols/index.d.ts.map +1 -1
  195. package/lib/WAUSync/Protocols/index.js +0 -1
  196. package/lib/WAUSync/Protocols/index.js.map +1 -1
  197. package/lib/WAUSync/USyncQuery.d.ts +0 -1
  198. package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
  199. package/lib/WAUSync/USyncQuery.js +2 -6
  200. package/lib/WAUSync/USyncQuery.js.map +1 -1
  201. package/lib/WAUSync/USyncUser.d.ts +0 -4
  202. package/lib/WAUSync/USyncUser.d.ts.map +1 -1
  203. package/lib/WAUSync/USyncUser.js +0 -8
  204. package/lib/WAUSync/USyncUser.js.map +1 -1
  205. package/lib/index.d.ts +1 -1
  206. package/lib/index.d.ts.map +1 -1
  207. package/lib/index.js +1 -4
  208. package/lib/index.js.map +1 -1
  209. package/package.json +30 -34
  210. package/LICENSE +0 -21
  211. package/engine-requirements.js +0 -10
  212. package/lib/Socket/smgss.d.ts +0 -119
  213. package/lib/Socket/smgss.d.ts.map +0 -1
  214. package/lib/Socket/smgss.js +0 -453
  215. package/lib/Socket/smgss.js.map +0 -1
  216. package/lib/Store/index.d.ts +0 -4
  217. package/lib/Store/index.d.ts.map +0 -1
  218. package/lib/Store/index.js +0 -4
  219. package/lib/Store/index.js.map +0 -1
  220. package/lib/Store/make-in-memory-store.d.ts +0 -132
  221. package/lib/Store/make-in-memory-store.d.ts.map +0 -1
  222. package/lib/Store/make-in-memory-store.js +0 -450
  223. package/lib/Store/make-in-memory-store.js.map +0 -1
  224. package/lib/Store/make-ordered-dictionary.d.ts +0 -14
  225. package/lib/Store/make-ordered-dictionary.d.ts.map +0 -1
  226. package/lib/Store/make-ordered-dictionary.js +0 -80
  227. package/lib/Store/make-ordered-dictionary.js.map +0 -1
  228. package/lib/Store/object-repository.d.ts +0 -13
  229. package/lib/Store/object-repository.d.ts.map +0 -1
  230. package/lib/Store/object-repository.js +0 -24
  231. package/lib/Store/object-repository.js.map +0 -1
  232. package/lib/Types/Mex.d.ts.map +0 -1
  233. package/lib/Types/Mex.js.map +0 -1
  234. package/lib/Utils/button-handler.d.ts +0 -28
  235. package/lib/Utils/button-handler.d.ts.map +0 -1
  236. package/lib/Utils/button-handler.js +0 -140
  237. package/lib/Utils/button-handler.js.map +0 -1
  238. package/lib/Utils/companion-reg-client-utils.d.ts +0 -17
  239. package/lib/Utils/companion-reg-client-utils.d.ts.map +0 -1
  240. package/lib/Utils/companion-reg-client-utils.js +0 -35
  241. package/lib/Utils/companion-reg-client-utils.js.map +0 -1
  242. package/lib/Utils/interactive.d.ts +0 -60
  243. package/lib/Utils/interactive.d.ts.map +0 -1
  244. package/lib/Utils/interactive.js +0 -224
  245. package/lib/Utils/interactive.js.map +0 -1
  246. package/lib/Utils/message-composer.d.ts +0 -93
  247. package/lib/Utils/message-composer.d.ts.map +0 -1
  248. package/lib/Utils/message-composer.js +0 -311
  249. package/lib/Utils/message-composer.js.map +0 -1
  250. package/lib/Utils/messages-newsletter.d.ts +0 -74
  251. package/lib/Utils/messages-newsletter.d.ts.map +0 -1
  252. package/lib/Utils/messages-newsletter.js +0 -128
  253. package/lib/Utils/messages-newsletter.js.map +0 -1
  254. package/lib/Utils/shortcake-crypto.d.ts +0 -36
  255. package/lib/Utils/shortcake-crypto.d.ts.map +0 -1
  256. package/lib/Utils/shortcake-crypto.js +0 -71
  257. package/lib/Utils/shortcake-crypto.js.map +0 -1
  258. package/lib/Utils/shortcake.d.ts +0 -36
  259. package/lib/Utils/shortcake.d.ts.map +0 -1
  260. package/lib/Utils/shortcake.js +0 -162
  261. package/lib/Utils/shortcake.js.map +0 -1
  262. package/lib/Utils/use-single-file-auth-state.d.ts +0 -6
  263. package/lib/Utils/use-single-file-auth-state.d.ts.map +0 -1
  264. package/lib/Utils/use-single-file-auth-state.js +0 -111
  265. package/lib/Utils/use-single-file-auth-state.js.map +0 -1
  266. package/lib/Utils/use-sqlite-auth-state.d.ts +0 -14
  267. package/lib/Utils/use-sqlite-auth-state.d.ts.map +0 -1
  268. package/lib/Utils/use-sqlite-auth-state.js +0 -107
  269. package/lib/Utils/use-sqlite-auth-state.js.map +0 -1
  270. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +0 -10
  271. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +0 -1
  272. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +0 -25
  273. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { Boom } from '@hapi/boom';
2
- import { spawn } from 'child_process';
2
+ import { exec } from 'child_process';
3
3
  import * as Crypto from 'crypto';
4
4
  import { once } from 'events';
5
5
  import { createReadStream, createWriteStream, promises as fs, WriteStream } from 'fs';
@@ -13,31 +13,16 @@ import { getBinaryNodeChild, getBinaryNodeChildBuffer, jidNormalizedUser } from
13
13
  import { aesDecryptGCM, aesEncryptGCM, hkdf } from './crypto.js';
14
14
  import { generateMessageIDV2 } from './generics.js';
15
15
  const getTmpFilesDirectory = () => tmpdir();
16
- let imageProcessingLibrary;
17
- export const getImageProcessingLibrary = async () => {
18
- if (imageProcessingLibrary) {
19
- return imageProcessingLibrary;
20
- }
16
+ const getImageProcessingLibrary = async () => {
21
17
  //@ts-ignore
22
- const [jimp, sharp, napi] = await Promise.all([
23
- import('jimp').catch(() => { }),
24
- import('sharp').catch(() => { }),
25
- //@ts-ignore
26
- import('@napi-rs/image').catch(() => { })
27
- ]);
18
+ const [jimp, sharp] = await Promise.all([import('jimp').catch(() => { }), import('sharp').catch(() => { })]);
28
19
  if (sharp) {
29
- imageProcessingLibrary = { sharp };
30
- }
31
- else if (napi) {
32
- imageProcessingLibrary = { napi };
33
- }
34
- else if (jimp) {
35
- imageProcessingLibrary = { jimp };
20
+ return { sharp };
36
21
  }
37
- else {
38
- throw new Boom('No image processing library available');
22
+ if (jimp) {
23
+ return { jimp };
39
24
  }
40
- return imageProcessingLibrary;
25
+ throw new Boom('No image processing library available');
41
26
  };
42
27
  export const hkdfInfoKey = (type) => {
43
28
  const hkdfInfo = MEDIA_HKDF_KEY_MAPPING[type];
@@ -99,32 +84,13 @@ export async function getMediaKeys(buffer, mediaType) {
99
84
  }
100
85
  /** Extracts video thumb using FFMPEG */
101
86
  const extractVideoThumb = async (path, destPath, time, size) => new Promise((resolve, reject) => {
102
- const args = [
103
- '-ss',
104
- time,
105
- '-i',
106
- path,
107
- '-y',
108
- '-vf',
109
- `scale=${size.width}:-1`,
110
- '-vframes',
111
- '1',
112
- '-f',
113
- 'image2',
114
- destPath
115
- ];
116
- const child = spawn('ffmpeg', args);
117
- let stderr = '';
118
- child.stderr?.on('data', chunk => {
119
- stderr += chunk;
120
- });
121
- child.on('error', reject);
122
- child.on('close', code => {
123
- if (code === 0) {
124
- resolve();
87
+ const cmd = `ffmpeg -ss ${time} -i ${path} -y -vf scale=${size.width}:-1 -vframes 1 -f image2 ${destPath}`;
88
+ exec(cmd, err => {
89
+ if (err) {
90
+ reject(err);
125
91
  }
126
92
  else {
127
- reject(new Boom(`ffmpeg exited with code ${code}`, { data: stderr }));
93
+ resolve();
128
94
  }
129
95
  });
130
96
  });
@@ -161,28 +127,14 @@ export const extractImageThumb = async (bufferOrFilePath, width = 32) => {
161
127
  original: dimensions
162
128
  };
163
129
  }
164
- else if ('napi' in lib && typeof lib.napi?.Transformer === 'function') {
165
- const input = typeof bufferOrFilePath === 'string' ? await fs.readFile(bufferOrFilePath) : bufferOrFilePath;
166
- const img = new lib.napi.Transformer(input);
167
- const meta = await img.metadata();
168
- const buffer = await img.resize(width).jpeg(50);
169
- return {
170
- buffer,
171
- original: {
172
- width: meta.width,
173
- height: meta.height
174
- }
175
- };
176
- }
177
130
  else {
178
131
  throw new Boom('No image processing library available');
179
132
  }
180
133
  };
181
134
  export const encodeBase64EncodedStringForUpload = (b64) => encodeURIComponent(b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, ''));
182
- export const generateProfilePicture = async (mediaUpload, dimensions, opts) => {
135
+ export const generateProfilePicture = async (mediaUpload, dimensions) => {
183
136
  let buffer;
184
- const { full = true } = opts || {};
185
- const { width: w = full ? 720 : 640, height: h = full ? 720 : 640 } = dimensions || {};
137
+ const { width: w = 640, height: h = 640 } = dimensions || {};
186
138
  if (Buffer.isBuffer(mediaUpload)) {
187
139
  buffer = mediaUpload;
188
140
  }
@@ -197,38 +149,17 @@ export const generateProfilePicture = async (mediaUpload, dimensions, opts) => {
197
149
  if ('sharp' in lib && typeof lib.sharp?.default === 'function') {
198
150
  img = lib.sharp
199
151
  .default(buffer)
200
- .resize(w, h, full ? { fit: 'inside', withoutEnlargement: false } : undefined)
152
+ .resize(w, h)
201
153
  .jpeg({
202
- quality: full ? 100 : 50
154
+ quality: 50
203
155
  })
204
156
  .toBuffer();
205
157
  }
206
158
  else if ('jimp' in lib && typeof lib.jimp?.Jimp === 'function') {
207
159
  const jimp = await lib.jimp.Jimp.read(buffer);
208
- let resized;
209
- if (full) {
210
- const scale = Math.min(w / jimp.width, h / jimp.height, 1);
211
- const targetW = Math.max(1, Math.round(jimp.width * scale));
212
- const targetH = Math.max(1, Math.round(jimp.height * scale));
213
- resized = jimp.resize({ w: targetW, h: targetH, mode: lib.jimp.ResizeStrategy.BILINEAR });
214
- }
215
- else {
216
- const min = Math.min(jimp.width, jimp.height);
217
- const cropped = jimp.crop({ x: 0, y: 0, w: min, h: min });
218
- resized = cropped.resize({ w, h, mode: lib.jimp.ResizeStrategy.BILINEAR });
219
- }
220
- img = resized.getBuffer('image/jpeg', { quality: full ? 100 : 50 });
221
- }
222
- else if ('napi' in lib && typeof lib.napi?.Transformer === 'function') {
223
- const transformer = new lib.napi.Transformer(buffer);
224
- const meta = await transformer.metadata();
225
- if (full) {
226
- img = transformer.resize(w, h).jpeg(100);
227
- }
228
- else {
229
- const min = Math.min(meta.width, meta.height);
230
- img = transformer.crop(0, 0, min, min).resize(w, h).jpeg(50);
231
- }
160
+ const min = Math.min(jimp.width, jimp.height);
161
+ const cropped = jimp.crop({ x: 0, y: 0, w: min, h: min });
162
+ img = cropped.resize({ w, h, mode: lib.jimp.ResizeStrategy.BILINEAR }).getBuffer('image/jpeg', { quality: 50 });
232
163
  }
233
164
  else {
234
165
  throw new Boom('No image processing library available');
@@ -375,34 +306,35 @@ export const getHttpStream = async (url, options = {}) => {
375
306
  // @ts-ignore Node18+ Readable.fromWeb exists
376
307
  return response.body instanceof Readable ? response.body : Readable.fromWeb(response.body);
377
308
  };
378
- export const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
309
+ export const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts, mediaKey: providedMediaKey } = {}) => {
379
310
  const { stream, type } = await getStream(media, opts);
380
- logger?.debug('fetched media stream');
381
- const mediaKey = Crypto.randomBytes(32);
311
+ let finalStream = stream;
312
+ const mediaKey = providedMediaKey || Crypto.randomBytes(32);
382
313
  const { cipherKey, iv, macKey } = await getMediaKeys(mediaKey, mediaType);
383
- const encFilePath = join(getTmpFilesDirectory(), mediaType + generateMessageIDV2() + '-enc');
384
- const encFileWriteStream = createWriteStream(encFilePath);
385
- let originalFileStream;
386
- let originalFilePath;
387
- if (saveOriginalFileIfRequired) {
388
- originalFilePath = join(getTmpFilesDirectory(), mediaType + generateMessageIDV2() + '-original');
389
- originalFileStream = createWriteStream(originalFilePath);
314
+ const encWriteStream = new Readable({ read: () => {}, highWaterMark: 64 * 1024 });
315
+ let bodyPath;
316
+ let writeStream;
317
+ let didSaveToTmpPath = false;
318
+ if (type === 'file') {
319
+ bodyPath = media.url?.toString?.() || media.url;
320
+ }
321
+ else if (saveOriginalFileIfRequired) {
322
+ bodyPath = join(getTmpFilesDirectory(), mediaType + generateMessageIDV2());
323
+ writeStream = createWriteStream(bodyPath);
324
+ didSaveToTmpPath = true;
390
325
  }
391
326
  let fileLength = 0;
392
327
  const aes = Crypto.createCipheriv('aes-256-cbc', cipherKey, iv);
393
- const hmac = Crypto.createHmac('sha256', macKey).update(iv);
394
- const sha256Plain = Crypto.createHash('sha256');
395
- const sha256Enc = Crypto.createHash('sha256');
396
- const onChunk = async (buff) => {
397
- sha256Enc.update(buff);
398
- hmac.update(buff);
399
- // Handle backpressure: if write returns false, wait for drain
400
- if (!encFileWriteStream.write(buff)) {
401
- await once(encFileWriteStream, 'drain');
402
- }
328
+ let hmac = Crypto.createHmac('sha256', macKey).update(iv);
329
+ let sha256Plain = Crypto.createHash('sha256');
330
+ let sha256Enc = Crypto.createHash('sha256');
331
+ const onChunk = (buff) => {
332
+ sha256Enc = sha256Enc.update(buff);
333
+ hmac = hmac.update(buff);
334
+ encWriteStream.push(buff);
403
335
  };
404
336
  try {
405
- for await (const data of stream) {
337
+ for await (const data of finalStream) {
406
338
  fileLength += data.length;
407
339
  if (type === 'remote' &&
408
340
  opts?.maxContentLength &&
@@ -411,82 +343,59 @@ export const encryptedStream = async (media, mediaType, { logger, saveOriginalFi
411
343
  data: { media, type }
412
344
  });
413
345
  }
414
- if (originalFileStream) {
415
- if (!originalFileStream.write(data)) {
416
- await once(originalFileStream, 'drain');
346
+ sha256Plain = sha256Plain.update(data);
347
+ if (writeStream) {
348
+ if (!writeStream.write(data)) {
349
+ await once(writeStream, 'drain');
417
350
  }
418
351
  }
419
- sha256Plain.update(data);
420
- await onChunk(aes.update(data));
352
+ onChunk(aes.update(data));
421
353
  }
422
- await onChunk(aes.final());
354
+ onChunk(aes.final());
423
355
  const mac = hmac.digest().slice(0, 10);
424
- sha256Enc.update(mac);
356
+ sha256Enc = sha256Enc.update(mac);
425
357
  const fileSha256 = sha256Plain.digest();
426
358
  const fileEncSha256 = sha256Enc.digest();
427
- encFileWriteStream.write(mac);
428
- const encFinishPromise = once(encFileWriteStream, 'finish');
429
- const originalFinishPromise = originalFileStream ? once(originalFileStream, 'finish') : Promise.resolve();
430
- encFileWriteStream.end();
431
- originalFileStream?.end?.();
432
- stream.destroy();
433
- // Wait for write streams to fully flush to disk
434
- // This helps reduce memory pressure by allowing OS to release buffers
435
- await encFinishPromise;
436
- await originalFinishPromise;
437
- logger?.debug('encrypted data successfully');
359
+ encWriteStream.push(mac);
360
+ encWriteStream.push(null);
361
+ writeStream?.end?.();
362
+ if (writeStream) await once(writeStream, 'finish');
363
+ finalStream.destroy();
438
364
  return {
439
365
  mediaKey,
440
- originalFilePath,
441
- encFilePath,
366
+ encWriteStream,
367
+ bodyPath,
442
368
  mac,
443
369
  fileEncSha256,
444
370
  fileSha256,
445
- fileLength
371
+ fileLength,
372
+ didSaveToTmpPath
446
373
  };
447
374
  }
448
375
  catch (error) {
449
- // destroy all streams with error
450
- encFileWriteStream.destroy();
451
- originalFileStream?.destroy?.();
376
+ encWriteStream.destroy();
377
+ writeStream?.destroy?.();
452
378
  aes.destroy();
453
379
  hmac.destroy();
454
380
  sha256Plain.destroy();
455
381
  sha256Enc.destroy();
456
382
  stream.destroy();
457
- try {
458
- await fs.unlink(encFilePath);
459
- if (originalFilePath) {
460
- await fs.unlink(originalFilePath);
461
- }
462
- }
463
- catch (err) {
464
- logger?.error({ err }, 'failed deleting tmp files');
383
+ if (didSaveToTmpPath) {
384
+ try { await fs.unlink(bodyPath); } catch (_) {}
465
385
  }
466
386
  throw error;
467
387
  }
468
388
  };
469
- export const DEF_MEDIA_HOST = 'mmg.whatsapp.net';
389
+
390
+ const DEF_HOST = 'mmg.whatsapp.net';
470
391
  const AES_CHUNK_SIZE = 16;
471
392
  const toSmallestChunkSize = (num) => {
472
393
  return Math.floor(num / AES_CHUNK_SIZE) * AES_CHUNK_SIZE;
473
394
  };
474
- export const getUrlFromDirectPath = (directPath, host = DEF_MEDIA_HOST) => `https://${host}${directPath}`;
475
- const extractHost = (url) => {
476
- if (!url)
477
- return undefined;
478
- try {
479
- return new URL(url).host;
480
- }
481
- catch {
482
- return undefined;
483
- }
484
- };
395
+ export const getUrlFromDirectPath = (directPath) => `https://${DEF_HOST}${directPath}`;
485
396
  export const downloadContentFromMessage = async ({ mediaKey, directPath, url }, type, opts = {}) => {
486
- // Fallback host: explicit opt > host parsed from `url` > DEF_MEDIA_HOST.
487
- // Lets us honor a non-default host carried by the proto without forcing callers to thread it through.
488
- const fallbackHost = opts.host ?? extractHost(url);
489
- const downloadUrl = directPath ? getUrlFromDirectPath(directPath, fallbackHost) : url;
397
+ const isValidMediaUrl = url?.startsWith('https://mmg.whatsapp.net/');
398
+ const downloadUrl = isValidMediaUrl ? url : getUrlFromDirectPath(directPath);
490
399
  if (!downloadUrl) {
491
400
  throw new Boom('No valid media URL or directPath present in message', { statusCode: 400 });
492
401
  }
@@ -546,7 +455,7 @@ export const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, {
546
455
  };
547
456
  const output = new Transform({
548
457
  transform(chunk, _, callback) {
549
- let data = remainingBytes.length ? Buffer.concat([remainingBytes, chunk]) : chunk;
458
+ let data = Buffer.concat([remainingBytes, chunk]);
550
459
  const decryptLength = toSmallestChunkSize(data.length);
551
460
  remainingBytes = data.slice(decryptLength);
552
461
  data = data.slice(0, decryptLength);
@@ -665,10 +574,8 @@ const uploadWithFetch = async ({ url, filePath, headers, timeoutMs, agent }) =>
665
574
  // Convert Node.js Readable to Web ReadableStream
666
575
  const nodeStream = createReadStream(filePath);
667
576
  const webStream = Readable.toWeb(nodeStream);
668
- // Native fetch only accepts Undici-style dispatchers, not generic https Agents.
669
- const dispatcher = typeof agent?.dispatch === 'function' ? agent : undefined;
670
577
  const response = await fetch(url, {
671
- ...(dispatcher ? { dispatcher } : {}),
578
+ dispatcher: agent,
672
579
  method: 'POST',
673
580
  body: webStream,
674
581
  headers,
@@ -710,17 +617,14 @@ const uploadMedia = async (params, logger) => {
710
617
  }
711
618
  };
712
619
  export const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
713
- return async (filePath, { mediaType, fileEncSha256B64, timeoutMs }) => {
714
- // send a query JSON to obtain the url & auth token to upload our media
620
+ return async (streamOrPath, { mediaType, fileEncSha256B64, newsletter, timeoutMs }) => {
715
621
  let uploadInfo = await refreshMediaConn(false);
716
622
  let urls;
717
623
  const hosts = [...customUploadHosts, ...uploadInfo.hosts];
718
624
  fileEncSha256B64 = encodeBase64EncodedStringForUpload(fileEncSha256B64);
719
- // Prepare common headers
720
625
  const customHeaders = (() => {
721
626
  const hdrs = options?.headers;
722
- if (!hdrs)
723
- return {};
627
+ if (!hdrs) return {};
724
628
  return Array.isArray(hdrs) ? Object.fromEntries(hdrs) : hdrs;
725
629
  })();
726
630
  const headers = {
@@ -728,23 +632,43 @@ export const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, opt
728
632
  'Content-Type': 'application/octet-stream',
729
633
  Origin: DEFAULT_ORIGIN
730
634
  };
635
+ let reqBuffer;
636
+ if (Buffer.isBuffer(streamOrPath)) {
637
+ reqBuffer = streamOrPath;
638
+ }
639
+ else if (typeof streamOrPath === 'string') {
640
+ reqBuffer = await fs.readFile(streamOrPath);
641
+ }
642
+ else {
643
+ const chunks = [];
644
+ for await (const chunk of streamOrPath) chunks.push(chunk);
645
+ reqBuffer = Buffer.concat(chunks);
646
+ }
647
+ let mediaPath = MEDIA_PATH_MAP[mediaType];
648
+ if (newsletter && mediaPath) {
649
+ mediaPath = mediaPath.replace('/mms/', '/newsletter/newsletter-');
650
+ }
731
651
  for (const { hostname } of hosts) {
732
652
  logger.debug(`uploading to "${hostname}"`);
733
653
  const auth = encodeURIComponent(uploadInfo.auth);
734
- const url = `https://${hostname}${MEDIA_PATH_MAP[mediaType]}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
654
+ const url = `https://${hostname}${mediaPath}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
735
655
  let result;
736
656
  try {
737
- result = await uploadMedia({
738
- url,
739
- filePath,
657
+ const axios = (await import('axios')).default;
658
+ const body = await axios.post(url, reqBuffer, {
740
659
  headers,
741
- timeoutMs,
742
- agent: fetchAgent
743
- }, logger);
660
+ httpsAgent: fetchAgent,
661
+ timeout: timeoutMs,
662
+ responseType: 'json',
663
+ maxBodyLength: Infinity,
664
+ maxContentLength: Infinity
665
+ });
666
+ result = body.data;
744
667
  if (result?.url || result?.direct_path) {
745
668
  urls = {
746
669
  mediaUrl: result.url,
747
670
  directPath: result.direct_path,
671
+ handle: result.handle,
748
672
  meta_hmac: result.meta_hmac,
749
673
  fbid: result.fbid,
750
674
  ts: result.ts
@@ -767,6 +691,7 @@ export const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, opt
767
691
  return urls;
768
692
  };
769
693
  };
694
+
770
695
  const getMediaRetryKey = (mediaKey) => {
771
696
  return hkdf(mediaKey, 32, { info: 'WhatsApp Media Retry Notification' });
772
697
  };
@@ -854,124 +779,4 @@ const MEDIA_RETRY_STATUS_MAP = {
854
779
  [proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404,
855
780
  [proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418
856
781
  };
857
- const runFfmpegBuffer = (args, input) => {
858
- return new Promise((resolve, reject) => {
859
- const ff = spawn('ffmpeg', args, { stdio: ['pipe', 'pipe', 'ignore'] });
860
- const chunks = [];
861
- let len = 0;
862
- ff.stdout.on('data', (c) => {
863
- chunks.push(c);
864
- len += c.length;
865
- });
866
- ff.on('close', code => (code === 0 ? resolve(Buffer.concat(chunks, len)) : reject(new Boom(`ffmpeg exited with code ${code}`))));
867
- ff.on('error', reject);
868
- ff.stdin.end(input);
869
- });
870
- };
871
- export const resizeImage = async (buf, width, height, opts = {}) => {
872
- const { quality = 80 } = opts;
873
- const lib = await getImageProcessingLibrary();
874
- if ('sharp' in lib && typeof lib.sharp?.default === 'function') {
875
- return lib.sharp.default(buf).resize(width, height, { fit: 'inside' }).jpeg({ quality }).toBuffer();
876
- }
877
- //@ts-ignore
878
- const jimpMod = await import('jimp').catch(() => undefined);
879
- if (jimpMod) {
880
- const Jimp = jimpMod.default || jimpMod;
881
- const img = await Jimp.read(buf);
882
- img.resize(width, height);
883
- img.quality(quality);
884
- return img.getBufferAsync(Jimp.MIME_JPEG);
885
- }
886
- throw new Boom('resizeImage requires "sharp" or "jimp" to be installed', { statusCode: 500 });
887
- };
888
- export const convertMedia = async (buf, opts) => {
889
- const fmt = opts.to.toLowerCase().replace('.', '');
890
- const imageFormats = { jpeg: 'jpeg', jpg: 'jpeg', png: 'png', webp: 'webp' };
891
- if (imageFormats[fmt]) {
892
- const lib = await getImageProcessingLibrary();
893
- if ('sharp' in lib && typeof lib.sharp?.default === 'function') {
894
- return lib.sharp.default(buf).toFormat(imageFormats[fmt]).toBuffer();
895
- }
896
- throw new Boom('convertMedia to an image format requires "sharp" to be installed', { statusCode: 500 });
897
- }
898
- const args = ['-i', 'pipe:0', '-y'];
899
- if (fmt === 'mp4') {
900
- args.push('-movflags', 'frag_keyframe+empty_moov', '-f', 'mp4');
901
- }
902
- else {
903
- args.push('-f', fmt);
904
- }
905
- args.push('pipe:1');
906
- return runFfmpegBuffer(args, buf);
907
- };
908
- export const imageToWebpSticker = async (buf, opts = {}) => {
909
- const { quality = 80 } = opts;
910
- const lib = await getImageProcessingLibrary();
911
- if ('sharp' in lib && typeof lib.sharp?.default === 'function') {
912
- return lib.sharp
913
- .default(buf)
914
- .resize(512, 512, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })
915
- .webp({ quality })
916
- .toBuffer();
917
- }
918
- throw new Boom('imageToWebpSticker requires "sharp" to be installed', { statusCode: 500 });
919
- };
920
- export const compressMedia = async (buf, opts = {}) => {
921
- const { quality = 50 } = opts;
922
- const lib = await getImageProcessingLibrary();
923
- if ('sharp' in lib && typeof lib.sharp?.default === 'function') {
924
- try {
925
- const { format } = await lib.sharp.default(buf).metadata();
926
- if (format) {
927
- return lib.sharp.default(buf).toFormat(format, { quality }).toBuffer();
928
- }
929
- }
930
- catch { }
931
- }
932
- const crf = String(Math.round(51 - (quality / 100) * 51));
933
- return runFfmpegBuffer(['-i', 'pipe:0', '-y', '-crf', crf, '-preset', 'ultrafast', '-movflags', 'frag_keyframe+empty_moov', '-f', 'mp4', 'pipe:1'], buf);
934
- };
935
- export const getMediaMetadata = async (buf) => {
936
- const result = { size: buf.length };
937
- const lib = await getImageProcessingLibrary();
938
- if ('sharp' in lib && typeof lib.sharp?.default === 'function') {
939
- try {
940
- const meta = await lib.sharp.default(buf).metadata();
941
- if (meta.format) {
942
- result.mimetype = `image/${meta.format}`;
943
- result.width = meta.width;
944
- result.height = meta.height;
945
- result.channels = meta.channels;
946
- result.hasAlpha = meta.hasAlpha;
947
- return result;
948
- }
949
- }
950
- catch { }
951
- }
952
- return new Promise(resolve => {
953
- const ff = spawn('ffprobe', ['-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', 'pipe:0'], {
954
- stdio: ['pipe', 'pipe', 'ignore']
955
- });
956
- const chunks = [];
957
- ff.stdout.on('data', (c) => chunks.push(c));
958
- ff.on('close', () => {
959
- try {
960
- const d = JSON.parse(Buffer.concat(chunks).toString());
961
- const vid = d.streams?.find((s) => s.codec_type === 'video');
962
- const aud = d.streams?.find((s) => s.codec_type === 'audio');
963
- if (vid) {
964
- result.width = vid.width;
965
- result.height = vid.height;
966
- }
967
- result.duration = parseFloat(d.format?.duration) || undefined;
968
- result.mimetype = vid ? 'video/mp4' : aud ? 'audio/mpeg' : undefined;
969
- }
970
- catch { }
971
- resolve(result);
972
- });
973
- ff.on('error', () => resolve(result));
974
- ff.stdin.end(buf);
975
- });
976
- };
977
782
  //# sourceMappingURL=messages-media.js.map