Skip to content

Commit 7b7f47a

Browse files
Update whatsapp.business.service.ts
Sticker and Location to Catch it is not available.
1 parent 2ded197 commit 7b7f47a

File tree

1 file changed

+132
-51
lines changed

1 file changed

+132
-51
lines changed

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

Lines changed: 132 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -191,34 +191,64 @@ export class BusinessStartupService extends ChannelStartupService {
191191
return content;
192192
}
193193

194-
private messageTextJson(received: any) {
195-
let content: any;
196-
const message = received.messages[0];
197-
if (message.from === received.metadata.phone_number_id) {
198-
content = {
199-
extendedTextMessage: { text: message.text.body },
200-
};
201-
message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
194+
private messageTextJson(received: any) {
195+
// Verificar que received y received.messages existen
196+
if (!received || !received.messages || received.messages.length === 0) {
197+
this.logger.error('Error: received object or messages array is undefined or empty');
198+
return null;
199+
}
200+
201+
const message = received.messages[0];
202+
let content: any;
203+
204+
// Verificar si es un mensaje de tipo sticker, location u otro tipo que no tiene text
205+
if (!message.text) {
206+
// Si no hay texto, manejamos diferente según el tipo de mensaje
207+
if (message.type === 'sticker') {
208+
content = { stickerMessage: {} };
209+
} else if (message.type === 'location') {
210+
content = { locationMessage: {
211+
degreesLatitude: message.location?.latitude,
212+
degreesLongitude: message.location?.longitude,
213+
name: message.location?.name,
214+
address: message.location?.address,
215+
}};
202216
} else {
203-
content = { conversation: message.text.body };
204-
message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
217+
// Para otros tipos de mensajes sin texto, creamos un contenido genérico
218+
this.logger.log(`Mensaje de tipo ${message.type} sin campo text`);
219+
content = { [message.type + 'Message']: message[message.type] || {} };
220+
}
221+
222+
// Añadir contexto si existe
223+
if (message.context) {
224+
content = { ...content, contextInfo: { stanzaId: message.context.id } };
205225
}
226+
206227
return content;
207228
}
229+
230+
// Si el mensaje tiene texto, procesamos normalmente
231+
if (!received.metadata || !received.metadata.phone_number_id) {
232+
this.logger.error('Error: metadata or phone_number_id is undefined');
233+
return null;
234+
}
208235

209-
private messageLocationJson(received: any) {
210-
const message = received.messages[0];
211-
let content: any = {
212-
locationMessage: {
213-
degreesLatitude: message.location.latitude,
214-
degreesLongitude: message.location.longitude,
215-
name: message.location?.name,
216-
address: message.location?.address,
217-
},
236+
if (message.from === received.metadata.phone_number_id) {
237+
content = {
238+
extendedTextMessage: { text: message.text.body },
218239
};
219-
message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
220-
return content;
240+
if (message.context) {
241+
content = { ...content, contextInfo: { stanzaId: message.context.id } };
242+
}
243+
} else {
244+
content = { conversation: message.text.body };
245+
if (message.context) {
246+
content = { ...content, contextInfo: { stanzaId: message.context.id } };
247+
}
221248
}
249+
250+
return content;
251+
}
222252

223253
private messageContactsJson(received: any) {
224254
const message = received.messages[0];
@@ -277,7 +307,7 @@ export class BusinessStartupService extends ChannelStartupService {
277307

278308
private renderMessageType(type: string) {
279309
let messageType: string;
280-
310+
281311
switch (type) {
282312
case 'text':
283313
messageType = 'conversation';
@@ -300,28 +330,48 @@ export class BusinessStartupService extends ChannelStartupService {
300330
case 'location':
301331
messageType = 'locationMessage';
302332
break;
333+
case 'sticker':
334+
messageType = 'stickerMessage';
335+
break;
303336
default:
304337
messageType = 'conversation';
305338
break;
306339
}
307-
340+
308341
return messageType;
309342
}
310343

311344
protected async messageHandle(received: any, database: Database, settings: any) {
312345
try {
313346
let messageRaw: any;
314347
let pushName: any;
315-
348+
316349
if (received.contacts) pushName = received.contacts[0].profile.name;
317-
350+
318351
if (received.messages) {
352+
const message = received.messages[0]; // Añadir esta línea para definir message
353+
319354
const key = {
320-
id: received.messages[0].id,
355+
id: message.id,
321356
remoteJid: this.phoneNumber,
322-
fromMe: received.messages[0].from === received.metadata.phone_number_id,
357+
fromMe: message.from === received.metadata.phone_number_id,
323358
};
324-
if (this.isMediaMessage(received?.messages[0])) {
359+
360+
if (message.type === 'sticker') {
361+
this.logger.log('Procesando mensaje de tipo sticker');
362+
messageRaw = {
363+
key,
364+
pushName,
365+
message: {
366+
stickerMessage: message.sticker || {},
367+
},
368+
messageType: 'stickerMessage',
369+
messageTimestamp: parseInt(message.timestamp) as number,
370+
source: 'unknown',
371+
instanceId: this.instanceId,
372+
};
373+
} else if (this.isMediaMessage(message)) {
374+
325375
messageRaw = {
326376
key,
327377
pushName,
@@ -455,17 +505,6 @@ export class BusinessStartupService extends ChannelStartupService {
455505
source: 'unknown',
456506
instanceId: this.instanceId,
457507
};
458-
} else if (received?.messages[0].location) {
459-
messageRaw = {
460-
key,
461-
pushName,
462-
message: this.messageLocationJson(received),
463-
contextInfo: this.messageLocationJson(received)?.contextInfo,
464-
messageType: this.renderMessageType(received.messages[0].type),
465-
messageTimestamp: parseInt(received.messages[0].timestamp) as number,
466-
source: 'unknown',
467-
instanceId: this.instanceId,
468-
};
469508
} else {
470509
messageRaw = {
471510
key,
@@ -539,7 +578,7 @@ export class BusinessStartupService extends ChannelStartupService {
539578
}
540579
}
541580

542-
if (!this.isMediaMessage(received?.messages[0])) {
581+
if (!this.isMediaMessage(message) && message.type !== 'sticker') {
543582
await this.prismaRepository.message.create({
544583
data: messageRaw,
545584
});
@@ -742,10 +781,47 @@ export class BusinessStartupService extends ChannelStartupService {
742781
}
743782

744783
protected async eventHandler(content: any) {
745-
const database = this.configService.get<Database>('DATABASE');
746-
const settings = await this.findSettings();
747-
748-
this.messageHandle(content, database, settings);
784+
try {
785+
// Registro para depuración
786+
this.logger.log('Contenido recibido en eventHandler:');
787+
this.logger.log(JSON.stringify(content, null, 2));
788+
789+
const database = this.configService.get<Database>('DATABASE');
790+
const settings = await this.findSettings();
791+
792+
// Si hay mensajes, verificar primero el tipo
793+
if (content.messages && content.messages.length > 0) {
794+
const message = content.messages[0];
795+
this.logger.log(`Tipo de mensaje recibido: ${message.type}`);
796+
797+
// Verificamos el tipo de mensaje antes de procesarlo
798+
if (message.type === 'text' ||
799+
message.type === 'image' ||
800+
message.type === 'video' ||
801+
message.type === 'audio' ||
802+
message.type === 'document' ||
803+
message.type === 'sticker' ||
804+
message.type === 'location' ||
805+
message.type === 'contacts' ||
806+
message.type === 'interactive' ||
807+
message.type === 'button' ||
808+
message.type === 'reaction') {
809+
810+
// Procesar el mensaje normalmente
811+
this.messageHandle(content, database, settings);
812+
} else {
813+
this.logger.warn(`Tipo de mensaje no reconocido: ${message.type}`);
814+
}
815+
} else if (content.statuses) {
816+
// Procesar actualizaciones de estado
817+
this.messageHandle(content, database, settings);
818+
} else {
819+
this.logger.warn('No se encontraron mensajes ni estados en el contenido recibido');
820+
}
821+
} catch (error) {
822+
this.logger.error('Error en eventHandler:');
823+
this.logger.error(error);
824+
}
749825
}
750826

751827
protected async sendMessageWithTyping(number: string, message: any, options?: Options, isIntegration = false) {
@@ -828,7 +904,6 @@ export class BusinessStartupService extends ChannelStartupService {
828904
}
829905
if (message['media']) {
830906
const isImage = message['mimetype']?.startsWith('image/');
831-
const isVideo = message['mimetype']?.startsWith('video/');
832907

833908
content = {
834909
messaging_product: 'whatsapp',
@@ -838,7 +913,7 @@ export class BusinessStartupService extends ChannelStartupService {
838913
[message['mediaType']]: {
839914
[message['type']]: message['id'],
840915
preview_url: linkPreview,
841-
...(message['fileName'] && !isImage && !isVideo && { filename: message['fileName'] }),
916+
...(message['fileName'] && !isImage && { filename: message['fileName'] }),
842917
caption: message['caption'],
843918
},
844919
};
@@ -1006,10 +1081,8 @@ export class BusinessStartupService extends ChannelStartupService {
10061081

10071082
private async getIdMedia(mediaMessage: any) {
10081083
const formData = new FormData();
1009-
const media = mediaMessage.media || mediaMessage.audio;
1010-
if (!media) throw new Error('Media or audio not found');
10111084

1012-
const fileStream = createReadStream(media);
1085+
const fileStream = createReadStream(mediaMessage.media);
10131086

10141087
formData.append('file', fileStream, { filename: 'media', contentType: mediaMessage.mimetype });
10151088
formData.append('typeFile', mediaMessage.mimetype);
@@ -1110,7 +1183,7 @@ export class BusinessStartupService extends ChannelStartupService {
11101183
const prepareMedia: any = {
11111184
fileName: `${hash}.mp3`,
11121185
mediaType: 'audio',
1113-
audio,
1186+
media: audio,
11141187
};
11151188

11161189
if (isURL(audio)) {
@@ -1132,7 +1205,15 @@ export class BusinessStartupService extends ChannelStartupService {
11321205
public async audioWhatsapp(data: SendAudioDto, file?: any, isIntegration = false) {
11331206
const mediaData: SendAudioDto = { ...data };
11341207

1135-
if (file) mediaData.audio = file.buffer.toString('base64');
1208+
if (file?.buffer) {
1209+
mediaData.audio = file.buffer.toString('base64');
1210+
} else if (isURL(mediaData.audio)) {
1211+
// DO NOTHING
1212+
// mediaData.audio = mediaData.audio;
1213+
} else {
1214+
console.error('El archivo no tiene buffer o file es undefined');
1215+
throw new Error('File or buffer is undefined');
1216+
}
11361217

11371218
const message = await this.processAudio(mediaData.audio, data.number);
11381219

0 commit comments

Comments
 (0)