From 75474a90d66d20bb96163efcb200a68453993007 Mon Sep 17 00:00:00 2001 From: Kishan Date: Fri, 23 Aug 2024 11:37:02 +1000 Subject: [PATCH 1/2] feat: added a decrypt and save function --- package-lock.json | 74 +++++++++------------------ package.json | 2 +- src/api/helpers/decrypt.ts | 62 ++++++++++++++++++++-- src/api/whatsapp.ts | 102 +++++++++++++++++++++++++++++++++++-- 4 files changed, 182 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index a9b0f857b..5af0e08d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "logform": "^2.6.1", "lookpath": "^1.2.2", "mime-types": "^2.1.35", - "puppeteer": "^22.15.0", + "puppeteer": "^23.0.2", "puppeteer-extra": "^3.3.6", "puppeteer-extra-plugin-stealth": "^2.11.2", "puppeteer-extra-plugin-user-data-dir": "^2.4.1", @@ -3841,7 +3841,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.0.tgz", "integrity": "sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA==", - "license": "Apache-2.0", "dependencies": { "debug": "^4.3.5", "extract-zip": "^2.0.1", @@ -3863,7 +3862,6 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -4140,7 +4138,6 @@ "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "license": "MIT", "optional": true, "dependencies": { "@types/node": "*" @@ -4611,8 +4608,8 @@ }, "node_modules/@wppconnect/wa-js": { "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@wppconnect/wa-js/-/wa-js-3.8.1.tgz", - "integrity": "sha512-BBYZie7UocgssoJOtDlRWjUqKcyWbxxlmHqcGJO+0A8ANV/enoFQvXaN9RSiWPQk1Un7oDWmtXpMuRHJ1w2Fig==", + "resolved": "file:../../npm-packages/wppconnect-wa-js-3.8.1.tgz", + "integrity": "sha512-/c/nuod0vRDIbSB+hgqe8sjKJ2uMBuwT1F23qr63hXKlXi7egi45Ogmbf/692swabXx4bQG8vVSXsYaHxlO06g==", "license": "Apache-2.0", "engines": { "whatsapp-web": ">=2.2326.10-beta" @@ -4962,8 +4959,7 @@ "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", - "license": "Apache-2.0" + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" }, "node_modules/babel-loader": { "version": "9.1.3", @@ -5035,14 +5031,12 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", - "license": "Apache-2.0", "optional": true }, "node_modules/bare-fs": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz", "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", - "license": "Apache-2.0", "optional": true, "dependencies": { "bare-events": "^2.0.0", @@ -5054,14 +5048,12 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz", "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", - "license": "Apache-2.0", "optional": true }, "node_modules/bare-path": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", - "license": "Apache-2.0", "optional": true, "dependencies": { "bare-os": "^2.1.0" @@ -5071,7 +5063,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", - "license": "Apache-2.0", "optional": true, "dependencies": { "streamx": "^2.18.0" @@ -5251,7 +5242,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "license": "MIT", "engines": { "node": "*" } @@ -5497,10 +5487,9 @@ } }, "node_modules/chromium-bidi": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.3.tgz", - "integrity": "sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A==", - "license": "Apache-2.0", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz", + "integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==", "dependencies": { "mitt": "3.0.1", "urlpattern-polyfill": "10.0.0", @@ -6656,8 +6645,7 @@ "node_modules/devtools-protocol": { "version": "0.0.1312386", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", - "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", - "license": "BSD-3-Clause" + "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==" }, "node_modules/diff": { "version": "5.2.0", @@ -7368,7 +7356,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -7388,7 +7375,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "license": "MIT", "dependencies": { "pump": "^3.0.0" }, @@ -7416,8 +7402,7 @@ "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "license": "MIT" + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, "node_modules/fast-glob": { "version": "3.3.2", @@ -7487,7 +7472,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "license": "MIT", "dependencies": { "pend": "~1.2.0" } @@ -9676,8 +9660,7 @@ "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "license": "MIT" + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" }, "node_modules/mixin-object": { "version": "2.0.1", @@ -10467,8 +10450,7 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "license": "MIT" + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, "node_modules/picocolors": { "version": "1.0.1", @@ -10700,7 +10682,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -10800,32 +10781,32 @@ } }, "node_modules/puppeteer": { - "version": "22.15.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.15.0.tgz", - "integrity": "sha512-XjCY1SiSEi1T7iSYuxS82ft85kwDJUS7wj1Z0eGVXKdtr5g4xnVcbjwxhq5xBnpK/E7x1VZZoJDxpjAOasHT4Q==", + "version": "23.0.2", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.0.2.tgz", + "integrity": "sha512-I/l1P8s8brcLG+oW9AwF8hUaOSGGJcGKMflXRgULUH0S3ABptlLI9ZKjqWDo8ipY6v789ZKd+bNKtcCwpTh5Ww==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.3.0", + "chromium-bidi": "0.6.4", "cosmiconfig": "^9.0.0", "devtools-protocol": "0.0.1312386", - "puppeteer-core": "22.15.0" + "puppeteer-core": "23.0.2" }, "bin": { - "puppeteer": "lib/esm/puppeteer/node/cli.js" + "puppeteer": "lib/cjs/puppeteer/node/cli.js" }, "engines": { "node": ">=18" } }, "node_modules/puppeteer-core": { - "version": "22.15.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.15.0.tgz", - "integrity": "sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA==", - "license": "Apache-2.0", + "version": "23.0.2", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.0.2.tgz", + "integrity": "sha512-MvOHn+g1TYkAR2oVd/bf/YWXKqFTJmkhyyurYgxkrjh8rBOL1ZH5VyOsLJi0bLO7/yoipAmk1gFZEx9HUJnaoA==", "dependencies": { "@puppeteer/browsers": "2.3.0", - "chromium-bidi": "0.6.3", + "chromium-bidi": "0.6.4", "debug": "^4.3.6", "devtools-protocol": "0.0.1312386", "ws": "^8.18.0" @@ -11016,8 +10997,7 @@ "node_modules/queue-tick": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "license": "MIT" + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" }, "node_modules/quick-lru": { "version": "5.1.1", @@ -12758,7 +12738,6 @@ "version": "2.18.0", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", - "license": "MIT", "dependencies": { "fast-fifo": "^1.3.2", "queue-tick": "^1.0.1", @@ -12891,7 +12870,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", - "license": "MIT", "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" @@ -12905,7 +12883,6 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "license": "MIT", "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", @@ -13049,7 +13026,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", - "license": "Apache-2.0", "dependencies": { "b4a": "^1.6.4" } @@ -13383,7 +13359,6 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "license": "MIT", "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -13830,8 +13805,7 @@ "node_modules/urlpattern-polyfill": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "license": "MIT" + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" }, "node_modules/utf8-byte-length": { "version": "1.0.5", @@ -14429,7 +14403,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -14475,7 +14448,6 @@ "version": "3.23.8", "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 040f8a219..139d122ba 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "logform": "^2.6.1", "lookpath": "^1.2.2", "mime-types": "^2.1.35", - "puppeteer": "^22.15.0", + "puppeteer": "^23.0.2", "puppeteer-extra": "^3.3.6", "puppeteer-extra-plugin-stealth": "^2.11.2", "puppeteer-extra-plugin-user-data-dir": "^2.4.1", diff --git a/src/api/helpers/decrypt.ts b/src/api/helpers/decrypt.ts index e80f210cd..adb464f4d 100644 --- a/src/api/helpers/decrypt.ts +++ b/src/api/helpers/decrypt.ts @@ -17,11 +17,15 @@ import * as crypto from 'crypto'; import hkdf from 'futoin-hkdf'; -import atob = require('atob'); +import atob from 'atob'; import { ResponseType } from 'axios'; +import { Transform } from 'stream'; -export const makeOptions = (useragentOverride: string) => ({ - responseType: 'arraybuffer' as ResponseType, +export const makeOptions = ( + useragentOverride: string, + responseType: ResponseType = 'arraybuffer' +) => ({ + responseType: responseType, headers: { 'User-Agent': processUA(useragentOverride), DNT: '1', @@ -110,3 +114,55 @@ const base64ToBytes = (base64Str: any) => { } return byteArray; }; + +export const newMagix = ( + mediaKeyBase64: string, + mediaType: string, + expectedSize: number +) => { + const mediaKeyBytes = newBase64ToBytes(mediaKeyBase64); + const info = `WhatsApp ${mediaTypes[mediaType.toUpperCase()]} Keys`; + const hash = 'sha256'; + const salt = Buffer.alloc(32); + const expandedSize = 112; + const mediaKeyExpanded = hkdf(mediaKeyBytes, expandedSize, { + salt, + info, + hash, + }); + const iv = mediaKeyExpanded.slice(0, 16); + const cipherKey = mediaKeyExpanded.slice(16, 48); + + const decipher = crypto.createDecipheriv('aes-256-cbc', cipherKey, iv); + let processedBytes: number = 0; + let buffer = Buffer.alloc(0); + + const transformStream = new Transform({ + transform(chunk, encoding, callback) { + try { + const decryptedChunk = decipher.update(chunk); + processedBytes += decryptedChunk.length; + if (processedBytes > expectedSize) { + const paddedChunk = Buffer.from(decryptedChunk).slice( + 0, + buffer.length - (processedBytes - expectedSize) + ); + callback(null, paddedChunk); + } else { + callback(null, decryptedChunk); + } + } catch (error: any) { + callback(error); + } + }, + }); + + transformStream.on('error', (error) => { + console.error('Error during decryption:', error); + }); + + return transformStream; +}; + +const newBase64ToBytes = (base64Str: string) => + Buffer.from(base64Str, 'base64'); diff --git a/src/api/whatsapp.ts b/src/api/whatsapp.ts index 385469ae3..0195fc8c8 100644 --- a/src/api/whatsapp.ts +++ b/src/api/whatsapp.ts @@ -20,10 +20,11 @@ import { Page } from 'puppeteer'; import { CreateConfig } from '../config/create-config'; import { useragentOverride } from '../config/WAuserAgente'; import { evaluateAndReturn } from './helpers'; -import { magix, makeOptions, timeout } from './helpers/decrypt'; +import { magix, makeOptions, newMagix, timeout } from './helpers/decrypt'; import { BusinessLayer } from './layers/business.layer'; import { GetMessagesParam, Message } from './model'; -import treekill = require('tree-kill'); +import * as fs from 'fs'; +import { sleep } from '../utils/sleep'; export class Whatsapp extends BusinessLayer { private connected: boolean | null = null; @@ -39,7 +40,7 @@ export class Whatsapp extends BusinessLayer { }); } - interval = setInterval(async (state) => { + interval = setInterval(async () => { const newConnected = await page .evaluate(() => WPP.conn.isRegistered()) .catch(() => null); @@ -232,6 +233,101 @@ export class Whatsapp extends BusinessLayer { return magix(buff, message.mediaKey, message.type, message.size); } + public async decryptAndSaveFile( + message: Message, + savePath: string + ): Promise { + const mediaUrl = message.clientUrl || message.deprecatedMms3Url; + + if (!mediaUrl) { + throw new Error( + 'Message is missing critical data needed to download the file.' + ); + } + + try { + const tempSavePath: string = savePath + '.encrypted'; + await this.downloadEncryptedFile(mediaUrl.trim(), tempSavePath); + + const inputReadStream = fs.createReadStream(tempSavePath); + const outputWriteStream = fs.createWriteStream(savePath); + const decryptedStream = newMagix( + message.mediaKey, + message.type, + message.size + ); + + inputReadStream.pipe(decryptedStream).pipe(outputWriteStream); + + await new Promise((resolve, reject) => { + outputWriteStream.on('finish', () => { + console.log( + `Deciphering complete. Deleting the encrypted file: ${tempSavePath}` + ); + fs.unlink(tempSavePath, (error) => { + if (error) { + console.error( + `Error deleting the input file: ${tempSavePath}`, + error + ); + reject(error); + } else { + console.log('Encrypted file deleted successfully'); + resolve(); + } + }); + }); + + outputWriteStream.on('error', (error) => { + console.error(`Error during writing file: ${savePath}`, error); + reject(error); + }); + + decryptedStream.on('error', (error) => { + console.error('An error occurred while decrypting the file', error); + reject(error); + }); + }); + } catch (error) { + throw error; + } + } + + downloadEncryptedFile = async ( + url: string, + outputPath: string, + retries: number = 3 + ) => { + for (let attempt = 1; attempt <= retries; attempt++) { + try { + const response = await axios.get(url, makeOptions(useragentOverride)); + + await new Promise((resolve, reject) => { + const writer = fs.createWriteStream(outputPath); + response.data.pipe(writer); + writer.on('finish', resolve); + writer.on('error', reject); + }); + + console.log(`Encrypted file downloaded at ${outputPath}`); + return; + } catch (error) { + console.error(`Attempt ${attempt} failed: `, error.message); + if (attempt === retries) { + console.error( + `${outputPath} - All attempt failed to download the file: ${url}` + ); + throw error; + } + + console.log( + `${outputPath} - Retrying to download the file: ${url} in 5 seconds...` + ); + await sleep(5000); + } + } + }; + /** * Rejects a call received via WhatsApp * @param callId string Call ID, if not passed, all calls will be rejected From 132188a0e28b82bf2d0a36c08b990c8e9f3f186c Mon Sep 17 00:00:00 2001 From: Kishan Date: Fri, 23 Aug 2024 11:56:09 +1000 Subject: [PATCH 2/2] feat: passes stream when downloading encrypted file --- src/api/whatsapp.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api/whatsapp.ts b/src/api/whatsapp.ts index 0195fc8c8..46c114da4 100644 --- a/src/api/whatsapp.ts +++ b/src/api/whatsapp.ts @@ -300,7 +300,10 @@ export class Whatsapp extends BusinessLayer { ) => { for (let attempt = 1; attempt <= retries; attempt++) { try { - const response = await axios.get(url, makeOptions(useragentOverride)); + const response = await axios.get( + url, + makeOptions(useragentOverride, 'stream') + ); await new Promise((resolve, reject) => { const writer = fs.createWriteStream(outputPath);