mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-13 15:14:49 -06:00
refactor(whatsapp.business.service): enhance media handling and audio processing
- Updated media message preparation to conditionally include filename and caption based on media type. - Improved error handling in media ID retrieval and audio processing methods. - Refactored audio processing to support file uploads and URL handling more effectively. - Enhanced logging for better error tracking during media operations.
This commit is contained in:
parent
bc451e8493
commit
a02ecc88f5
@ -28,7 +28,6 @@ import axios from 'axios';
|
|||||||
import { arrayUnique, isURL } from 'class-validator';
|
import { arrayUnique, isURL } from 'class-validator';
|
||||||
import EventEmitter2 from 'eventemitter2';
|
import EventEmitter2 from 'eventemitter2';
|
||||||
import FormData from 'form-data';
|
import FormData from 'form-data';
|
||||||
import { createReadStream } from 'fs';
|
|
||||||
import mimeTypes from 'mime-types';
|
import mimeTypes from 'mime-types';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
@ -997,9 +996,10 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
to: number.replace(/\D/g, ''),
|
to: number.replace(/\D/g, ''),
|
||||||
[message['mediaType']]: {
|
[message['mediaType']]: {
|
||||||
[message['type']]: message['id'],
|
[message['type']]: message['id'],
|
||||||
preview_url: Boolean(options?.linkPreview),
|
...(message['mediaType'] !== 'audio' &&
|
||||||
...(message['fileName'] && !isImage && { filename: message['fileName'] }),
|
message['fileName'] &&
|
||||||
caption: message['caption'],
|
!isImage && { filename: message['fileName'] }),
|
||||||
|
...(message['mediaType'] !== 'audio' && message['caption'] && { caption: message['caption'] }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
quoted ? (content.context = { message_id: quoted.id }) : content;
|
quoted ? (content.context = { message_id: quoted.id }) : content;
|
||||||
@ -1097,7 +1097,7 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
if (messageSent?.error_data) {
|
if (messageSent?.error_data || messageSent.message) {
|
||||||
this.logger.error(messageSent);
|
this.logger.error(messageSent);
|
||||||
return messageSent;
|
return messageSent;
|
||||||
}
|
}
|
||||||
@ -1164,28 +1164,50 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getIdMedia(mediaMessage: any) {
|
private async getIdMedia(mediaMessage: any, isFile = false) {
|
||||||
const formData = new FormData();
|
try {
|
||||||
const fileStream = createReadStream(mediaMessage.media);
|
const formData = new FormData();
|
||||||
|
|
||||||
formData.append('file', fileStream, { filename: 'media', contentType: mediaMessage.mimetype });
|
if (isFile === false) {
|
||||||
formData.append('typeFile', mediaMessage.mimetype);
|
if (isURL(mediaMessage.media)) {
|
||||||
formData.append('messaging_product', 'whatsapp');
|
const response = await axios.get(mediaMessage.media, { responseType: 'arraybuffer' });
|
||||||
|
const buffer = Buffer.from(response.data, 'base64');
|
||||||
|
formData.append('file', buffer, {
|
||||||
|
filename: mediaMessage.fileName || 'media',
|
||||||
|
contentType: mediaMessage.mimetype,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const buffer = Buffer.from(mediaMessage.media, 'base64');
|
||||||
|
formData.append('file', buffer, {
|
||||||
|
filename: mediaMessage.fileName || 'media',
|
||||||
|
contentType: mediaMessage.mimetype,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
formData.append('file', mediaMessage.media.buffer, {
|
||||||
|
filename: mediaMessage.media.originalname,
|
||||||
|
contentType: mediaMessage.media.mimetype,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// const fileBuffer = await fs.readFile(mediaMessage.media);
|
const mimetype = mediaMessage.mimetype || mediaMessage.media.mimetype;
|
||||||
|
|
||||||
// const fileBlob = new Blob([fileBuffer], { type: mediaMessage.mimetype });
|
formData.append('typeFile', mimetype);
|
||||||
// formData.append('file', fileBlob);
|
formData.append('messaging_product', 'whatsapp');
|
||||||
// formData.append('typeFile', mediaMessage.mimetype);
|
|
||||||
// formData.append('messaging_product', 'whatsapp');
|
|
||||||
|
|
||||||
const headers = { Authorization: `Bearer ${this.token}` };
|
const token = process.env.FACEBOOK_USER_TOKEN;
|
||||||
const res = await axios.post(
|
|
||||||
process.env.API_URL + '/' + process.env.VERSION + '/' + this.number + '/media',
|
const headers = { Authorization: `Bearer ${token}` };
|
||||||
formData,
|
const url = `${this.configService.get<WaBusiness>('WA_BUSINESS').URL}/${
|
||||||
{ headers },
|
this.configService.get<WaBusiness>('WA_BUSINESS').VERSION
|
||||||
);
|
}/${this.number}/media`;
|
||||||
return res.data.id;
|
|
||||||
|
const res = await axios.post(url, formData, { headers });
|
||||||
|
return res.data.id;
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(error.response.data);
|
||||||
|
throw new InternalServerErrorException(error?.toString() || error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async prepareMediaMessage(mediaMessage: MediaMessage) {
|
protected async prepareMediaMessage(mediaMessage: MediaMessage) {
|
||||||
@ -1258,48 +1280,87 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
return mediaSent;
|
return mediaSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async processAudio(audio: string, number: string) {
|
public async processAudio(audio: string, number: string, file: any) {
|
||||||
number = number.replace(/\D/g, '');
|
number = number.replace(/\D/g, '');
|
||||||
const hash = `${number}-${new Date().getTime()}`;
|
const hash = `${number}-${new Date().getTime()}`;
|
||||||
|
|
||||||
let mimetype: string | false;
|
if (process.env.API_AUDIO_CONVERTER) {
|
||||||
|
this.logger.verbose('Using audio converter API');
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
const prepareMedia: any = {
|
if (file) {
|
||||||
fileName: `${hash}.mp3`,
|
formData.append('file', file.buffer, {
|
||||||
mediaType: 'audio',
|
filename: file.originalname,
|
||||||
media: audio,
|
contentType: file.mimetype,
|
||||||
};
|
});
|
||||||
|
} else if (isURL(audio)) {
|
||||||
|
formData.append('url', audio);
|
||||||
|
} else {
|
||||||
|
formData.append('base64', audio);
|
||||||
|
}
|
||||||
|
|
||||||
|
formData.append('format', 'mp3');
|
||||||
|
|
||||||
|
const response = await axios.post(process.env.API_AUDIO_CONVERTER, formData, {
|
||||||
|
headers: {
|
||||||
|
...formData.getHeaders(),
|
||||||
|
apikey: process.env.API_AUDIO_CONVERTER_KEY,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const audioConverter = response?.data?.audio || response?.data?.url;
|
||||||
|
|
||||||
|
if (!audioConverter) {
|
||||||
|
throw new InternalServerErrorException('Failed to convert audio');
|
||||||
|
}
|
||||||
|
|
||||||
|
const prepareMedia: any = {
|
||||||
|
fileName: `${hash}.mp3`,
|
||||||
|
mediaType: 'audio',
|
||||||
|
media: audioConverter,
|
||||||
|
mimetype: 'audio/mpeg',
|
||||||
|
};
|
||||||
|
|
||||||
if (isURL(audio)) {
|
|
||||||
mimetype = mimeTypes.lookup(audio);
|
|
||||||
prepareMedia.id = audio;
|
|
||||||
prepareMedia.type = 'link';
|
|
||||||
} else {
|
|
||||||
mimetype = mimeTypes.lookup(prepareMedia.fileName);
|
|
||||||
const id = await this.getIdMedia(prepareMedia);
|
const id = await this.getIdMedia(prepareMedia);
|
||||||
prepareMedia.id = id;
|
prepareMedia.id = id;
|
||||||
prepareMedia.type = 'id';
|
prepareMedia.type = 'id';
|
||||||
|
|
||||||
|
this.logger.verbose('Audio converted');
|
||||||
|
return prepareMedia;
|
||||||
|
} else {
|
||||||
|
let mimetype: string | false;
|
||||||
|
|
||||||
|
const prepareMedia: any = {
|
||||||
|
fileName: `${hash}.mp3`,
|
||||||
|
mediaType: 'audio',
|
||||||
|
media: audio,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isURL(audio)) {
|
||||||
|
mimetype = mimeTypes.lookup(audio);
|
||||||
|
prepareMedia.id = audio;
|
||||||
|
prepareMedia.type = 'link';
|
||||||
|
} else if (audio && !file) {
|
||||||
|
mimetype = mimeTypes.lookup(prepareMedia.fileName);
|
||||||
|
const id = await this.getIdMedia(prepareMedia);
|
||||||
|
prepareMedia.id = id;
|
||||||
|
prepareMedia.type = 'id';
|
||||||
|
} else if (file) {
|
||||||
|
prepareMedia.media = file;
|
||||||
|
const id = await this.getIdMedia(prepareMedia, true);
|
||||||
|
prepareMedia.id = id;
|
||||||
|
prepareMedia.type = 'id';
|
||||||
|
mimetype = file.mimetype;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareMedia.mimetype = mimetype;
|
||||||
|
|
||||||
|
return prepareMedia;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareMedia.mimetype = mimetype;
|
|
||||||
|
|
||||||
return prepareMedia;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async audioWhatsapp(data: SendAudioDto, file?: any, isIntegration = false) {
|
public async audioWhatsapp(data: SendAudioDto, file?: any, isIntegration = false) {
|
||||||
const mediaData: SendAudioDto = { ...data };
|
const message = await this.processAudio(data.audio, data.number, file);
|
||||||
|
|
||||||
if (file?.buffer) {
|
|
||||||
mediaData.audio = file.buffer.toString('base64');
|
|
||||||
} else if (isURL(mediaData.audio)) {
|
|
||||||
// DO NOTHING
|
|
||||||
// mediaData.audio = mediaData.audio;
|
|
||||||
} else {
|
|
||||||
console.error('El archivo no tiene buffer o file es undefined');
|
|
||||||
throw new Error('File or buffer is undefined');
|
|
||||||
}
|
|
||||||
|
|
||||||
const message = await this.processAudio(mediaData.audio, data.number);
|
|
||||||
|
|
||||||
const audioSent = await this.sendMessageWithTyping(
|
const audioSent = await this.sendMessageWithTyping(
|
||||||
data.number,
|
data.number,
|
||||||
|
@ -1819,7 +1819,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
// setTimeout(() => this.client.terminateCall(call.id, call.to), callDuration * 1000);
|
// setTimeout(() => this.client.terminateCall(call.id, call.to), callDuration * 1000);
|
||||||
|
|
||||||
// return call;
|
// return call;
|
||||||
return { id: '123' };
|
return { id: '123', jid, isVideo, callDuration };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user