Skip to content

Commit 614ad7c

Browse files
Merge pull request #1556 from splusoficial/develop
fix: adjustment in audio transcription with official api
2 parents e469dc1 + 77b3b33 commit 614ad7c

File tree

1 file changed

+108
-34
lines changed

1 file changed

+108
-34
lines changed

src/api/integrations/channel/meta/whatsapp.business.service.ts

Lines changed: 108 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -147,19 +147,44 @@ export class BusinessStartupService extends ChannelStartupService {
147147
const version = this.configService.get<WaBusiness>('WA_BUSINESS').VERSION;
148148
urlServer = `${urlServer}/${version}/${id}`;
149149
const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${this.token}` };
150+
151+
// Primeiro, obtenha a URL do arquivo
150152
let result = await axios.get(urlServer, { headers });
151-
result = await axios.get(result.data.url, { headers, responseType: 'arraybuffer' });
153+
154+
// Depois, baixe o arquivo usando a URL retornada
155+
result = await axios.get(result.data.url, {
156+
headers: { Authorization: `Bearer ${this.token}` }, // Use apenas o token de autorização para download
157+
responseType: 'arraybuffer',
158+
});
159+
152160
return result.data;
153161
} catch (e) {
154-
this.logger.error(e);
162+
this.logger.error(`Error downloading media: ${e}`);
163+
throw e;
155164
}
156165
}
157166

158167
private messageMediaJson(received: any) {
159168
const message = received.messages[0];
160169
let content: any = message.type + 'Message';
161170
content = { [content]: message[message.type] };
162-
message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
171+
if (message.context) {
172+
content = { ...content, contextInfo: { stanzaId: message.context.id } };
173+
}
174+
return content;
175+
}
176+
177+
private messageAudioJson(received: any) {
178+
const message = received.messages[0];
179+
let content: any = {
180+
audioMessage: {
181+
...message.audio,
182+
ptt: message.audio.voice || false, // Define se é mensagem de voz
183+
},
184+
};
185+
if (message.context) {
186+
content = { ...content, contextInfo: { stanzaId: message.context.id } };
187+
}
163188
return content;
164189
}
165190

@@ -387,11 +412,14 @@ export class BusinessStartupService extends ChannelStartupService {
387412
instanceId: this.instanceId,
388413
};
389414
} else if (this.isMediaMessage(message)) {
415+
const messageContent =
416+
message.type === 'audio' ? this.messageAudioJson(received) : this.messageMediaJson(received);
417+
390418
messageRaw = {
391419
key,
392420
pushName,
393-
message: this.messageMediaJson(received),
394-
contextInfo: this.messageMediaJson(received)?.contextInfo,
421+
message: messageContent,
422+
contextInfo: messageContent?.contextInfo,
395423
messageType: this.renderMessageType(received.messages[0].type),
396424
messageTimestamp: parseInt(received.messages[0].timestamp) as number,
397425
source: 'unknown',
@@ -409,7 +437,10 @@ export class BusinessStartupService extends ChannelStartupService {
409437
const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${this.token}` };
410438
const result = await axios.get(urlServer, { headers });
411439

412-
const buffer = await axios.get(result.data.url, { headers, responseType: 'arraybuffer' });
440+
const buffer = await axios.get(result.data.url, {
441+
headers: { Authorization: `Bearer ${this.token}` }, // Use apenas o token de autorização para download
442+
responseType: 'arraybuffer',
443+
});
413444

414445
let mediaType;
415446

@@ -434,6 +465,17 @@ export class BusinessStartupService extends ChannelStartupService {
434465
}
435466
}
436467

468+
// Para áudio, garantir extensão correta baseada no mimetype
469+
if (mediaType === 'audio') {
470+
if (mimetype.includes('ogg')) {
471+
fileName = `${message.messages[0].id}.ogg`;
472+
} else if (mimetype.includes('mp3')) {
473+
fileName = `${message.messages[0].id}.mp3`;
474+
} else if (mimetype.includes('m4a')) {
475+
fileName = `${message.messages[0].id}.m4a`;
476+
}
477+
}
478+
437479
const size = result.headers['content-length'] || buffer.data.byteLength;
438480

439481
const fullName = join(`${this.instance.id}`, key.remoteJid, mediaType, fileName);
@@ -460,13 +502,72 @@ export class BusinessStartupService extends ChannelStartupService {
460502

461503
messageRaw.message.mediaUrl = mediaUrl;
462504
messageRaw.message.base64 = buffer.data.toString('base64');
505+
506+
// Processar OpenAI speech-to-text para áudio após o mediaUrl estar disponível
507+
if (this.configService.get<Openai>('OPENAI').ENABLED && mediaType === 'audio') {
508+
const openAiDefaultSettings = await this.prismaRepository.openaiSetting.findFirst({
509+
where: {
510+
instanceId: this.instanceId,
511+
},
512+
include: {
513+
OpenaiCreds: true,
514+
},
515+
});
516+
517+
if (
518+
openAiDefaultSettings &&
519+
openAiDefaultSettings.openaiCredsId &&
520+
openAiDefaultSettings.speechToText
521+
) {
522+
try {
523+
messageRaw.message.speechToText = await this.openaiService.speechToText(
524+
openAiDefaultSettings.OpenaiCreds,
525+
{
526+
message: {
527+
mediaUrl: messageRaw.message.mediaUrl,
528+
...messageRaw,
529+
},
530+
},
531+
);
532+
} catch (speechError) {
533+
this.logger.error(`Error processing speech-to-text: ${speechError}`);
534+
}
535+
}
536+
}
463537
} catch (error) {
464538
this.logger.error(['Error on upload file to minio', error?.message, error?.stack]);
465539
}
466540
} else {
467541
const buffer = await this.downloadMediaMessage(received?.messages[0]);
468-
469542
messageRaw.message.base64 = buffer.toString('base64');
543+
544+
// Processar OpenAI speech-to-text para áudio mesmo sem S3
545+
if (this.configService.get<Openai>('OPENAI').ENABLED && message.type === 'audio') {
546+
const openAiDefaultSettings = await this.prismaRepository.openaiSetting.findFirst({
547+
where: {
548+
instanceId: this.instanceId,
549+
},
550+
include: {
551+
OpenaiCreds: true,
552+
},
553+
});
554+
555+
if (openAiDefaultSettings && openAiDefaultSettings.openaiCredsId && openAiDefaultSettings.speechToText) {
556+
try {
557+
messageRaw.message.speechToText = await this.openaiService.speechToText(
558+
openAiDefaultSettings.OpenaiCreds,
559+
{
560+
message: {
561+
base64: messageRaw.message.base64,
562+
...messageRaw,
563+
},
564+
},
565+
);
566+
} catch (speechError) {
567+
this.logger.error(`Error processing speech-to-text: ${speechError}`);
568+
}
569+
}
570+
}
470571
}
471572
} else if (received?.messages[0].interactive) {
472573
messageRaw = {
@@ -537,33 +638,6 @@ export class BusinessStartupService extends ChannelStartupService {
537638
// await this.client.readMessages([received.key]);
538639
}
539640

540-
if (this.configService.get<Openai>('OPENAI').ENABLED) {
541-
const openAiDefaultSettings = await this.prismaRepository.openaiSetting.findFirst({
542-
where: {
543-
instanceId: this.instanceId,
544-
},
545-
include: {
546-
OpenaiCreds: true,
547-
},
548-
});
549-
550-
const audioMessage = received?.messages[0]?.audio;
551-
552-
if (
553-
openAiDefaultSettings &&
554-
openAiDefaultSettings.openaiCredsId &&
555-
openAiDefaultSettings.speechToText &&
556-
audioMessage
557-
) {
558-
messageRaw.message.speechToText = await this.openaiService.speechToText(openAiDefaultSettings.OpenaiCreds, {
559-
message: {
560-
mediaUrl: messageRaw.message.mediaUrl,
561-
...messageRaw,
562-
},
563-
});
564-
}
565-
}
566-
567641
this.logger.log(messageRaw);
568642

569643
this.sendDataWebhook(Events.MESSAGES_UPSERT, messageRaw);

0 commit comments

Comments
 (0)