Stream uploads + downloads + allow for remote url uploads

- Switch to using got
- Use encryption/decryption streams for speed & lesser memory consumption
- Allow for stream based download & simultaneous upload of media
This commit is contained in:
Adhiraj Singh
2021-01-13 22:48:28 +05:30
parent 500805236a
commit 0344d6336c
19 changed files with 501 additions and 146 deletions

View File

@@ -1,4 +1,4 @@
import { WAConnection, MessageOptions, MessageType, unixTimestampSeconds, toNumber, GET_MESSAGE_ID, waMessageKey } from '../WAConnection/WAConnection'
import { WAConnection, MessageOptions, MessageType, unixTimestampSeconds, toNumber, GET_MESSAGE_ID, waMessageKey } from '../WAConnection'
import * as assert from 'assert'
import {promises as fs} from 'fs'

View File

@@ -1,5 +1,5 @@
import * as assert from 'assert'
import {WAConnection} from '../WAConnection/WAConnection'
import {WAConnection} from '../WAConnection'
import { AuthenticationCredentialsBase64, BaileysError, ReconnectMode, DisconnectReason, WAChat, WAContact } from '../WAConnection/Constants'
import { delay } from '../WAConnection/Utils'
import { assertChatDBIntegrity, makeConnection, testJid } from './Common'

View File

@@ -1,4 +1,4 @@
import { MessageType, GroupSettingChange, delay, ChatModification, whatsappID } from '../WAConnection/WAConnection'
import { MessageType, GroupSettingChange, delay, ChatModification, whatsappID } from '../WAConnection'
import * as assert from 'assert'
import { WAConnectionTest, testJid, sendAndRetreiveMessage } from './Common'

43
src/Tests/Tests.Media.ts Normal file
View File

@@ -0,0 +1,43 @@
import { deepStrictEqual, strictEqual } from 'assert'
import { createWriteStream } from 'fs'
import { readFile } from 'fs/promises'
import { proto } from '../../WAMessage/WAMessage'
import { MessageType } from '../WAConnection'
import { aesEncrypWithIV, decryptMediaMessageBuffer, encryptedStream, getMediaKeys, getStream, hmacSign, sha256 } from '../WAConnection/Utils'
import { WAConnectionTest } from './Common'
describe('Media Download Tests', () => {
it('should encrypt media streams correctly', async function() {
const url = './Media/meme.jpeg'
const streamValues = await encryptedStream({ url }, MessageType.image)
const buffer = await readFile(url)
const mediaKeys = getMediaKeys(streamValues.mediaKey, MessageType.image)
const enc = aesEncrypWithIV(buffer, mediaKeys.cipherKey, mediaKeys.iv)
const mac = hmacSign(Buffer.concat([mediaKeys.iv, enc]), mediaKeys.macKey).slice(0, 10)
const body = Buffer.concat([enc, mac]) // body is enc + mac
const fileSha256 = sha256(buffer)
const fileEncSha256 = sha256(body)
deepStrictEqual(streamValues.fileSha256, fileSha256)
strictEqual(streamValues.fileLength, buffer.length)
deepStrictEqual(streamValues.mac, mac)
deepStrictEqual(await readFile(streamValues.encBodyPath), body)
deepStrictEqual(streamValues.fileEncSha256, fileEncSha256)
})
})
/*
WAConnectionTest('Media Upload', conn => {
it('should upload the same file', async () => {
const FILES = [
{ url: './Media/meme.jpeg', type: MessageType.image },
{ url: './Media/ma_gif.mp4', type: MessageType.video },
{ url: './Media/sonata.mp3', type: MessageType.audio },
]
})
})*/

View File

@@ -1,7 +1,8 @@
import { MessageType, Mimetype, delay, promiseTimeout, WA_MESSAGE_STATUS_TYPE, WAMessageStatusUpdate, generateMessageID, WAMessage } from '../WAConnection/WAConnection'
import {promises as fs} from 'fs'
import { MessageType, Mimetype, delay, promiseTimeout, WA_MESSAGE_STATUS_TYPE, generateMessageID, WAMessage } from '../WAConnection'
import { promises as fs } from 'fs'
import * as assert from 'assert'
import { WAConnectionTest, testJid, sendAndRetreiveMessage, assertChatDBIntegrity } from './Common'
import { WAConnectionTest, testJid, sendAndRetreiveMessage } from './Common'
import { resolve } from 'path'
WAConnectionTest('Messages', conn => {
@@ -61,8 +62,7 @@ WAConnectionTest('Messages', conn => {
}
})
it('should send a gif', async () => {
const content = await fs.readFile('./Media/ma_gif.mp4')
const message = await sendAndRetreiveMessage(conn, content, MessageType.video, { mimetype: Mimetype.gif })
const message = await sendAndRetreiveMessage(conn, { url: './Media/ma_gif.mp4' }, MessageType.video, { mimetype: Mimetype.gif })
await conn.downloadAndSaveMediaMessage(message,'./Media/received_vid')
})
@@ -81,9 +81,18 @@ WAConnectionTest('Messages', conn => {
assert.strictEqual (message.message?.audioMessage?.ptt, true)
await conn.downloadAndSaveMediaMessage(message,'./Media/received_aud')
})
it('should send an image', async () => {
const content = await fs.readFile('./Media/meme.jpeg')
const message = await sendAndRetreiveMessage(conn, content, MessageType.image)
it('should send a jpeg image', async () => {
const message = await sendAndRetreiveMessage(conn, { url: './Media/meme.jpeg' }, MessageType.image)
assert.ok (message.message?.imageMessage?.jpegThumbnail)
const msg = await conn.downloadMediaMessage(message)
assert.deepStrictEqual(msg, await fs.readFile('./Media/meme.jpeg'))
})
it('should send a remote jpeg image', async () => {
const message = await sendAndRetreiveMessage(
conn,
{ url: 'https://www.memestemplates.com/wp-content/uploads/2020/05/tom-with-phone.jpg' },
MessageType.image
)
assert.ok (message.message?.imageMessage?.jpegThumbnail)
await conn.downloadMediaMessage(message)
})

View File

@@ -1,7 +1,7 @@
import { Presence, ChatModification, delay, newMessagesDB, WA_DEFAULT_EPHEMERAL, MessageType, WAMessage } from '../WAConnection/WAConnection'
import { Presence, ChatModification, delay, newMessagesDB, WA_DEFAULT_EPHEMERAL, MessageType, WAMessage } from '../WAConnection'
import { promises as fs } from 'fs'
import * as assert from 'assert'
import fetch from 'node-fetch'
import got from 'got'
import { WAConnectionTest, testJid, sendAndRetreiveMessage } from './Common'
WAConnectionTest('Misc', conn => {
@@ -79,15 +79,14 @@ WAConnectionTest('Misc', conn => {
await delay (5000)
const ppUrl = await conn.getProfilePicture(conn.user.jid)
const fetched = await fetch(ppUrl)
const buff = await fetched.buffer ()
const {rawBody: oldPP} = await got(ppUrl)
const newPP = await fs.readFile ('./Media/cat.jpeg')
const response = await conn.updateProfilePicture (conn.user.jid, newPP)
const newPP = await fs.readFile('./Media/cat.jpeg')
await conn.updateProfilePicture(conn.user.jid, newPP)
await delay (10000)
await conn.updateProfilePicture (conn.user.jid, buff) // revert back
await conn.updateProfilePicture (conn.user.jid, oldPP) // revert back
})
it('should return the profile picture', async () => {
const response = await conn.getProfilePicture(testJid)