mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-16 12:12:55 -06:00
feat: Added conversion of audios for sending recorded audio
This commit is contained in:
parent
ae1c5908ae
commit
2b2cc2effc
@ -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
|
||||||
|
|
||||||
|
@ -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",
|
||||||
|
@ -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
BIN
temp/audio.opus
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user