iachat/app/javascript/dashboard/api/inbox/message.js
Gabriel Jablonski ce39e54308
feat: add audio transcoding support for WhatsApp Cloud API (#220)
* feat: add audio transcoding support for WhatsApp Cloud API

- Introduced `Audio::TranscodeService` to handle audio transcoding to OGG/Opus format.
- Updated `Messages::MessageBuilder` to transcode audio attachments based on `transcode_audio` parameter.
- Enhanced `WhatsappCloudService` to normalize audio content types and send voice flag for recorded audio in OGG format.
- Added utility functions for audio conversion in JavaScript.
- Updated Dockerfile to include FFmpeg for audio processing.
- Added tests for audio transcoding and WhatsApp Cloud service interactions.

* feat: enhance audio handling with transcoding support and error management

* feat: improve audio transcoding error handling and enhance audio recording features

* feat: enhance audio transcoding process and error handling for better reliability

* feat: update recorded audio handling to support boolean and array formats
2026-02-22 16:21:50 -03:00

131 lines
3.0 KiB
JavaScript

/* eslint no-console: 0 */
/* global axios */
import ApiClient from '../ApiClient';
export const buildCreatePayload = ({
message,
isPrivate,
contentAttributes,
echoId,
files,
isRecordedAudio,
ccEmails = '',
bccEmails = '',
toEmails = '',
templateParams,
}) => {
let payload;
if (files && files.length !== 0) {
payload = new FormData();
if (message) {
payload.append('content', message);
}
files.forEach(file => {
payload.append('attachments[]', file);
});
if (isRecordedAudio === true) {
payload.append('is_recorded_audio', true);
} else if (Array.isArray(isRecordedAudio)) {
isRecordedAudio.forEach(filename => {
payload.append('is_recorded_audio[]', filename);
});
}
payload.append('private', isPrivate);
payload.append('echo_id', echoId);
payload.append('cc_emails', ccEmails);
payload.append('bcc_emails', bccEmails);
if (toEmails) {
payload.append('to_emails', toEmails);
}
if (contentAttributes) {
payload.append('content_attributes', JSON.stringify(contentAttributes));
}
} else {
payload = {
content: message,
private: isPrivate,
echo_id: echoId,
content_attributes: contentAttributes,
cc_emails: ccEmails,
bcc_emails: bccEmails,
to_emails: toEmails,
template_params: templateParams,
};
}
return payload;
};
class MessageApi extends ApiClient {
constructor() {
super('conversations', { accountScoped: true });
}
create({
conversationId,
message,
private: isPrivate,
contentAttributes,
echo_id: echoId,
files,
isRecordedAudio,
ccEmails = '',
bccEmails = '',
toEmails = '',
templateParams,
}) {
return axios({
method: 'post',
url: `${this.url}/${conversationId}/messages`,
data: buildCreatePayload({
message,
isPrivate,
contentAttributes,
echoId,
files,
isRecordedAudio,
ccEmails,
bccEmails,
toEmails,
templateParams,
}),
});
}
delete(conversationID, messageId) {
return axios.delete(`${this.url}/${conversationID}/messages/${messageId}`);
}
editContent(conversationID, messageId, content) {
return axios.patch(
`${this.url}/${conversationID}/messages/${messageId}/edit_content`,
{ content }
);
}
retry(conversationID, messageId) {
return axios.post(
`${this.url}/${conversationID}/messages/${messageId}/retry`
);
}
getPreviousMessages({ conversationId, after, before }) {
const params = { before };
if (after && Number(after) !== Number(before)) {
params.after = after;
}
return axios.get(`${this.url}/${conversationId}/messages`, { params });
}
translateMessage(conversationId, messageId, targetLanguage) {
return axios.post(
`${this.url}/${conversationId}/messages/${messageId}/translate`,
{
target_language: targetLanguage,
}
);
}
}
export default new MessageApi();