feat: Added conversion of audios for sending recorded audio

This commit is contained in:
Davidson Gomes 2023-06-11 10:29:49 -03:00
parent ae1c5908ae
commit 2b2cc2effc
4 changed files with 125 additions and 99 deletions

View File

@ -3,6 +3,7 @@
### Features ### Features
* Improved fetch instances endpoint, now it also fetch other instances even if they are not connected * Improved fetch instances endpoint, now it also fetch other instances even if they are not connected
* Added conversion of audios for sending recorded audio, now it is possible to send mp3 audios and not just ogg
### Fixed ### Fixed

View File

@ -42,6 +42,7 @@
"dependencies": { "dependencies": {
"@adiwajshing/keyed-db": "^0.2.4", "@adiwajshing/keyed-db": "^0.2.4",
"@evolution/base": "github:WhiskeySockets/Baileys", "@evolution/base": "github:WhiskeySockets/Baileys",
"@ffmpeg-installer/ffmpeg": "^1.1.0",
"@hapi/boom": "^10.0.1", "@hapi/boom": "^10.0.1",
"axios": "^1.3.5", "axios": "^1.3.5",
"class-validator": "^0.13.2", "class-validator": "^0.13.2",

View File

@ -40,6 +40,7 @@ import {
StoreConf, StoreConf,
Webhook, Webhook,
} from '../../config/env.config'; } from '../../config/env.config';
import fs from 'fs';
import { Logger } from '../../config/logger.config'; import { Logger } from '../../config/logger.config';
import { INSTANCE_DIR, ROOT_DIR } from '../../config/path.config'; import { INSTANCE_DIR, ROOT_DIR } from '../../config/path.config';
import { existsSync, readFileSync } from 'fs'; import { existsSync, readFileSync } from 'fs';
@ -53,7 +54,8 @@ import { Boom } from '@hapi/boom';
import EventEmitter2 from 'eventemitter2'; import EventEmitter2 from 'eventemitter2';
import { release } from 'os'; import { release } from 'os';
import P from 'pino'; import P from 'pino';
import { execSync } from 'child_process'; import { execSync, exec } from 'child_process';
import ffmpegPath from '@ffmpeg-installer/ffmpeg';
import { RepositoryBroker } from '../repository/repository.manager'; import { RepositoryBroker } from '../repository/repository.manager';
import { MessageRaw, MessageUpdateRaw } from '../models/message.model'; import { MessageRaw, MessageUpdateRaw } from '../models/message.model';
import { ContactRaw } from '../models/contact.model'; import { ContactRaw } from '../models/contact.model';
@ -207,93 +209,87 @@ export class WAStartupService {
} }
public async sendDataWebhook<T = any>(event: Events, data: T, local = true) { public async sendDataWebhook<T = any>(event: Events, data: T, local = true) {
const webhook = this.configService.get<Webhook>('WEBHOOK'); // const webhook = this.configService.get<Webhook>('WEBHOOK');
const we = event.replace(/[\.-]/gm, '_').toUpperCase(); // const we = event.replace(/[\.-]/gm, '_').toUpperCase();
const transformedWe = we.replace(/_/gm, '-').toLowerCase(); // const transformedWe = we.replace(/_/gm, '-').toLowerCase();
const instance = this.configService.get<Auth>('AUTHENTICATION').INSTANCE; // const instance = this.configService.get<Auth>('AUTHENTICATION').INSTANCE;
// if (webhook.EVENTS[we]) {
if (webhook.EVENTS[we]) { // if (local && instance.MODE !== 'container') {
if (local && instance.MODE !== 'container') { // const { WEBHOOK_BY_EVENTS } = instance;
const { WEBHOOK_BY_EVENTS } = instance; // let baseURL;
let baseURL; // if (WEBHOOK_BY_EVENTS) {
// baseURL = `${this.localWebhook.url}/${transformedWe}`;
if (WEBHOOK_BY_EVENTS) { // } else {
baseURL = `${this.localWebhook.url}/${transformedWe}`; // baseURL = this.localWebhook.url;
} else { // }
baseURL = this.localWebhook.url; // try {
} // if (this.localWebhook.enabled && isURL(this.localWebhook.url)) {
try { // const httpService = axios.create({ baseURL });
if (this.localWebhook.enabled && isURL(this.localWebhook.url)) { // await httpService.post('', {
const httpService = axios.create({ baseURL }); // event,
await httpService.post('', { // instance: this.instance.name,
event, // data,
instance: this.instance.name, // destination: this.localWebhook.url,
data, // });
destination: this.localWebhook.url, // }
}); // } catch (error) {
} // this.logger.error({
} catch (error) { // local: WAStartupService.name + '.sendDataWebhook-local',
this.logger.error({ // message: error?.message,
local: WAStartupService.name + '.sendDataWebhook-local', // hostName: error?.hostname,
message: error?.message, // syscall: error?.syscall,
hostName: error?.hostname, // code: error?.code,
syscall: error?.syscall, // error: error?.errno,
code: error?.code, // stack: error?.stack,
error: error?.errno, // name: error?.name,
stack: error?.stack, // url: baseURL,
name: error?.name, // });
url: baseURL, // }
}); // }
} // const globalWebhook = this.configService.get<Webhook>('WEBHOOK').GLOBAL;
} // let globalURL;
const globalWebhook = this.configService.get<Webhook>('WEBHOOK').GLOBAL; // if (webhook.GLOBAL.WEBHOOK_BY_EVENTS) {
let globalURL; // globalURL = `${globalWebhook.URL}/${transformedWe}`;
// } else {
if (webhook.GLOBAL.WEBHOOK_BY_EVENTS) { // globalURL = globalWebhook.URL;
globalURL = `${globalWebhook.URL}/${transformedWe}`; // }
} else { // let localUrl;
globalURL = globalWebhook.URL; // if (instance.MODE === 'container') {
} // localUrl = instance.WEBHOOK_URL;
// } else {
let localUrl; // localUrl = this.localWebhook.url;
// }
if (instance.MODE === 'container') { // this.logger.log({
localUrl = instance.WEBHOOK_URL; // url: globalURL,
} else { // event,
localUrl = this.localWebhook.url; // instance: this.instance.name,
} // data,
// destination: localUrl,
this.logger.log({ // });
url: globalURL, // try {
event, // if (globalWebhook && globalWebhook?.ENABLED && isURL(globalURL)) {
instance: this.instance.name, // const httpService = axios.create({ baseURL: globalURL });
data, // await httpService.post('', {
destination: localUrl, // event,
}); // instance: this.instance.name,
try { // data,
if (globalWebhook && globalWebhook?.ENABLED && isURL(globalURL)) { // destination: localUrl,
const httpService = axios.create({ baseURL: globalURL }); // });
await httpService.post('', { // }
event, // } catch (error) {
instance: this.instance.name, // this.logger.error({
data, // local: WAStartupService.name + '.sendDataWebhook-global',
destination: localUrl, // message: error?.message,
}); // hostName: error?.hostname,
} // syscall: error?.syscall,
} catch (error) { // code: error?.code,
this.logger.error({ // error: error?.errno,
local: WAStartupService.name + '.sendDataWebhook-global', // stack: error?.stack,
message: error?.message, // name: error?.name,
hostName: error?.hostname, // url: globalURL,
syscall: error?.syscall, // });
code: error?.code, // }
error: error?.errno, // }
stack: error?.stack,
name: error?.name,
url: globalURL,
});
}
}
} }
private async connectionUpdate({ private async connectionUpdate({
@ -1115,18 +1111,46 @@ export class WAStartupService {
); );
} }
private async processAudio(audio: string) {
const outputAudio = `${join(process.cwd(), 'temp', 'audio.opus')}`;
const response = await axios.get(audio, { responseType: 'arraybuffer' });
const tempAudioPath = `${join(process.cwd(), 'temp', 'audio.mp3')}`;
fs.writeFileSync(tempAudioPath, response.data);
return new Promise((resolve, reject) => {
exec(
`${ffmpegPath.path} -i ${tempAudioPath} -vn -c:a libopus -b:a 128k -ar 48000 ${outputAudio} -y`,
(error, _stdout, _stderr) => {
fs.unlinkSync(tempAudioPath);
if (error) reject(error);
resolve(outputAudio);
},
);
});
}
public async audioWhatsapp(data: SendAudioDto) { public async audioWhatsapp(data: SendAudioDto) {
return this.sendMessageWithTyping<AnyMessageContent>( const convert = await this.processAudio(data.audioMessage.audio);
data.number, if (typeof convert === 'string') {
{ const audio = fs.readFileSync(convert).toString('base64');
audio: isURL(data.audioMessage.audio) return this.sendMessageWithTyping<AnyMessageContent>(
? { url: data.audioMessage.audio } data.number,
: Buffer.from(data.audioMessage.audio, 'base64'), {
ptt: true, audio: Buffer.from(audio, 'base64'),
mimetype: 'audio/ogg; codecs=opus', // audio: isURL(data.audioMessage.audio)
}, // ? { url: data.audioMessage.audio }
{ presence: 'recording', delay: data?.options?.delay }, // : Buffer.from(data.audioMessage.audio, 'base64'),
); ptt: true,
mimetype: 'audio/ogg; codecs=opus',
},
{ presence: 'recording', delay: data?.options?.delay },
);
} else {
throw new InternalServerErrorException(convert);
}
} }
public async buttonMessage(data: SendButtonDto) { public async buttonMessage(data: SendButtonDto) {

BIN
temp/audio.opus Normal file

Binary file not shown.