Merge branch 'release/1.7.1'

This commit is contained in:
Davidson Gomes 2024-04-03 10:20:09 -03:00
commit 128119d494
5 changed files with 225 additions and 28 deletions

View File

@ -1,3 +1,14 @@
# 1.7.1 (2024-04-03 10:19)
### Fixed
* Correction when sending files with captions on Whatsapp Business
* Correction in receiving messages with response on WhatsApp Business
* Correction when sending a reaction to a message on WhatsApp Business
* Correction of receiving reactions on WhatsApp business
* Removed mandatory description of rows from sendList
* Feature to collect message type in typebot
# 1.7.0 (2024-03-11 18:23) # 1.7.0 (2024-03-11 18:23)
### Feature ### Feature

View File

@ -406,7 +406,7 @@ export const listMessageSchema: JSONSchema7 = {
description: { type: 'string' }, description: { type: 'string' },
rowId: { type: 'string' }, rowId: { type: 'string' },
}, },
required: ['title', 'description', 'rowId'], required: ['title', 'rowId'],
...isNotEmpty('title', 'description', 'rowId'), ...isNotEmpty('title', 'description', 'rowId'),
}, },
}, },

View File

@ -10,6 +10,7 @@ export class Session {
export class PrefilledVariables { export class PrefilledVariables {
remoteJid?: string; remoteJid?: string;
pushName?: string; pushName?: string;
messageType?: string;
additionalData?: { [key: string]: any }; additionalData?: { [key: string]: any };
} }

View File

@ -269,19 +269,27 @@ export class TypebotService {
} }
private getTypeMessage(msg: any) { private getTypeMessage(msg: any) {
this.logger.verbose('get type message'); this.logger.verbose('get type message');
const types = {
conversation: msg.conversation,
extendedTextMessage: msg.extendedTextMessage?.text,
audioMessage: msg.audioMessage?.url,
imageMessage: msg.imageMessage?.url,
videoMessage: msg.videoMessage?.url,
documentMessage: msg.documentMessage?.fileName,
contactMessage: msg.contactMessage?.displayName,
locationMessage: msg.locationMessage?.degreesLatitude,
viewOnceMessageV2: msg.viewOnceMessageV2?.message?.imageMessage?.url || msg.viewOnceMessageV2?.message?.videoMessage?.url || msg.viewOnceMessageV2?.message?.audioMessage?.url,
listResponseMessage: msg.listResponseMessage?.singleSelectReply?.selectedRowId,
responseRowId: msg.listResponseMessage?.singleSelectReply?.selectedRowId,
};
const types = { const messageType = Object.keys(types).find(key => types[key] !== undefined) || 'unknown';
conversation: msg.conversation,
extendedTextMessage: msg.extendedTextMessage?.text, this.logger.verbose('Type message: ' + JSON.stringify(types));
responseRowId: msg.listResponseMessage?.singleSelectReply?.selectedRowId, return { ...types, messageType };
};
this.logger.verbose('type message: ' + types);
return types;
} }
private getMessageContent(types: any) { private getMessageContent(types: any) {
this.logger.verbose('get message content'); this.logger.verbose('get message content');
const typeKey = Object.keys(types).find((key) => types[key] !== undefined); const typeKey = Object.keys(types).find((key) => types[key] !== undefined);
@ -305,6 +313,101 @@ export class TypebotService {
return messageContent; return messageContent;
} }
private getAudioMessageContent(msg: any) {
this.logger.verbose('get audio message content');
const types = this.getTypeMessage(msg);
const audioContent = types.audioMessage;
this.logger.verbose('audio message URL: ' + audioContent);
return audioContent;
}
private getImageMessageContent(msg: any) {
this.logger.verbose('get image message content');
const types = this.getTypeMessage(msg);
const imageContent = types.imageMessage;
this.logger.verbose('image message URL: ' + imageContent);
return imageContent;
}
private getVideoMessageContent(msg: any) {
this.logger.verbose('get video message content');
const types = this.getTypeMessage(msg);
const videoContent = types.videoMessage;
this.logger.verbose('video message URL: ' + videoContent);
return videoContent;
}
private getDocumentMessageContent(msg: any) {
this.logger.verbose('get document message content');
const types = this.getTypeMessage(msg);
const documentContent = types.documentMessage;
this.logger.verbose('document message fileName: ' + documentContent);
return documentContent;
}
private getContactMessageContent(msg: any) {
this.logger.verbose('get contact message content');
const types = this.getTypeMessage(msg);
const contactContent = types.contactMessage;
this.logger.verbose('contact message displayName: ' + contactContent);
return contactContent;
}
private getLocationMessageContent(msg: any) {
this.logger.verbose('get location message content');
const types = this.getTypeMessage(msg);
const locationContent = types.locationMessage;
this.logger.verbose('location message degreesLatitude: ' + locationContent);
return locationContent;
}
private getViewOnceMessageV2Content(msg: any) {
this.logger.verbose('get viewOnceMessageV2 content');
const types = this.getTypeMessage(msg);
const viewOnceContent = types.viewOnceMessageV2;
this.logger.verbose('viewOnceMessageV2 URL: ' + viewOnceContent);
return viewOnceContent;
}
private getListResponseMessageContent(msg: any) {
this.logger.verbose('get listResponseMessage content');
const types = this.getTypeMessage(msg);
const listResponseContent = types.listResponseMessage || types.responseRowId;
this.logger.verbose('listResponseMessage selectedRowId: ' + listResponseContent);
return listResponseContent;
}
public async createNewSession(instance: InstanceDto, data: any) { public async createNewSession(instance: InstanceDto, data: any) {
if (data.remoteJid === 'status@broadcast') return; if (data.remoteJid === 'status@broadcast') return;
const id = Math.floor(Math.random() * 10000000000).toString(); const id = Math.floor(Math.random() * 10000000000).toString();
@ -565,6 +668,7 @@ export class TypebotService {
const delay_message = findTypebot.delay_message; const delay_message = findTypebot.delay_message;
const unknown_message = findTypebot.unknown_message; const unknown_message = findTypebot.unknown_message;
const listening_from_me = findTypebot.listening_from_me; const listening_from_me = findTypebot.listening_from_me;
const messageType = this.getTypeMessage(msg.message).messageType;
const session = sessions.find((session) => session.remoteJid === remoteJid); const session = sessions.find((session) => session.remoteJid === remoteJid);
@ -687,6 +791,9 @@ export class TypebotService {
sessions: sessions, sessions: sessions,
remoteJid: remoteJid, remoteJid: remoteJid,
pushName: msg.pushName, pushName: msg.pushName,
prefilledVariables: {
messageType: messageType,
},
}); });
await this.sendWAMessage(instance, remoteJid, data.messages, data.input, data.clientSideActions); await this.sendWAMessage(instance, remoteJid, data.messages, data.input, data.clientSideActions);

View File

@ -183,14 +183,28 @@ export class BusinessStartupService extends WAStartupService {
const message = received.messages[0]; const message = received.messages[0];
let content: any = message.type + 'Message'; let content: any = message.type + 'Message';
content = { [content]: message[message.type] }; content = { [content]: message[message.type] };
message.context ? (content.extendedTextMessage = { contextInfo: { stanzaId: message.context.id } }) : content; message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
return content; return content;
} }
private messageInteractiveJson(received: any) { private messageInteractiveJson(received: any) {
const message = received.messages[0]; const message = received.messages[0];
const content: any = { conversation: message.interactive[message.interactive.type].title }; let content: any = { conversation: message.interactive[message.interactive.type].title };
message.context ? (content.extendedTextMessage = { contextInfo: { stanzaId: message.context.id } }) : content; message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
return content;
}
private messageReactionJson(received: any) {
const message = received.messages[0];
let content: any = {
reactionMessage: {
key: {
id: message.reaction.message_id,
},
text: message.reaction.emoji,
},
};
message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
return content; return content;
} }
@ -198,18 +212,20 @@ export class BusinessStartupService extends WAStartupService {
let content: any; let content: any;
const message = received.messages[0]; const message = received.messages[0];
if (message.from === received.metadata.phone_number_id) { if (message.from === received.metadata.phone_number_id) {
content = { extendedTextMessage: { text: message.text.body } }; content = {
message.context ? (content.extendedTextMessage.contextInfo = { stanzaId: message.context.id }) : content; extendedTextMessage: { text: message.text.body },
};
message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
} else { } else {
content = { conversation: message.text.body }; content = { conversation: message.text.body };
message.context ? (content.extendedTextMessage = { contextInfo: { stanzaId: message.context.id } }) : content; message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
} }
return content; return content;
} }
private messageContactsJson(received: any) { private messageContactsJson(received: any) {
const message = received.messages[0]; const message = received.messages[0];
const content: any = {}; let content: any = {};
const vcard = (contact: any) => { const vcard = (contact: any) => {
this.logger.verbose('Creating vcard'); this.logger.verbose('Creating vcard');
@ -264,7 +280,7 @@ export class BusinessStartupService extends WAStartupService {
}), }),
}; };
} }
message.context ? (content.extendedTextMessage = { contextInfo: { stanzaId: message.context.id } }) : content; message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
return content; return content;
} }
@ -287,8 +303,11 @@ export class BusinessStartupService extends WAStartupService {
case 'document': case 'document':
messageType = 'documentMessage'; messageType = 'documentMessage';
break; break;
case 'template':
messageType = 'conversation';
break;
default: default:
messageType = 'imageMessage'; messageType = 'conversation';
break; break;
} }
@ -339,6 +358,18 @@ export class BusinessStartupService extends WAStartupService {
owner: this.instance.name, owner: this.instance.name,
// source: getDevice(received.key.id), // source: getDevice(received.key.id),
}; };
} else if (received?.messages[0].reaction) {
messageRaw = {
key,
pushName,
message: {
...this.messageReactionJson(received),
},
messageType: 'reactionMessage',
messageTimestamp: received.messages[0].timestamp as number,
owner: this.instance.name,
// source: getDevice(received.key.id),
};
} else if (received?.messages[0].contacts) { } else if (received?.messages[0].contacts) {
messageRaw = { messageRaw = {
key, key,
@ -374,6 +405,7 @@ export class BusinessStartupService extends WAStartupService {
this.logger.log(messageRaw); this.logger.log(messageRaw);
this.logger.verbose('Sending data to webhook in event MESSAGES_UPSERT'); this.logger.verbose('Sending data to webhook in event MESSAGES_UPSERT');
this.sendDataWebhook(Events.MESSAGES_UPSERT, messageRaw); this.sendDataWebhook(Events.MESSAGES_UPSERT, messageRaw);
if (this.localChatwoot.enabled) { if (this.localChatwoot.enabled) {
@ -540,30 +572,68 @@ export class BusinessStartupService extends WAStartupService {
} }
} }
private convertMessageToRaw(message: any) { private convertMessageToRaw(message: any, content: any) {
let convertMessage: any;
if (message?.conversation) { if (message?.conversation) {
return message; if (content?.context?.message_id) {
convertMessage = {
...message,
contextInfo: { stanzaId: content.context.message_id },
};
return convertMessage;
}
convertMessage = message;
return convertMessage;
} }
if (message?.mediaType === 'image') { if (message?.mediaType === 'image') {
if (content?.context?.message_id) {
convertMessage = {
imageMessage: message,
contextInfo: { stanzaId: content.context.message_id },
};
return convertMessage;
}
return { return {
imageMessage: message, imageMessage: message,
}; };
} }
if (message?.mediaType === 'video') { if (message?.mediaType === 'video') {
if (content?.context?.message_id) {
convertMessage = {
videoMessage: message,
contextInfo: { stanzaId: content.context.message_id },
};
return convertMessage;
}
return { return {
videoMessage: message, videoMessage: message,
}; };
} }
if (message?.mediaType === 'audio') { if (message?.mediaType === 'audio') {
if (content?.context?.message_id) {
convertMessage = {
audioMessage: message,
contextInfo: { stanzaId: content.context.message_id },
};
return convertMessage;
}
return { return {
audioMessage: message, audioMessage: message,
}; };
} }
if (message?.mediaType === 'document') { if (message?.mediaType === 'document') {
if (content?.context?.message_id) {
convertMessage = {
documentMessage: message,
contextInfo: { stanzaId: content.context.message_id },
};
return convertMessage;
}
return { return {
documentMessage: message, documentMessage: message,
}; };
@ -610,7 +680,6 @@ export class BusinessStartupService extends WAStartupService {
message_id: message['reactionMessage']['key']['id'], message_id: message['reactionMessage']['key']['id'],
emoji: message['reactionMessage']['text'], emoji: message['reactionMessage']['text'],
}, },
context: { message_id: quoted.id },
}; };
quoted ? (content.context = { message_id: quoted.id }) : content; quoted ? (content.context = { message_id: quoted.id }) : content;
return await this.post(content, 'messages'); return await this.post(content, 'messages');
@ -670,6 +739,7 @@ export class BusinessStartupService extends WAStartupService {
[message['mediaType']]: { [message['mediaType']]: {
[message['type']]: message['id'], [message['type']]: message['id'],
preview_url: linkPreview, preview_url: linkPreview,
caption: message['caption'],
}, },
}; };
quoted ? (content.context = { message_id: quoted.id }) : content; quoted ? (content.context = { message_id: quoted.id }) : content;
@ -771,10 +841,17 @@ export class BusinessStartupService extends WAStartupService {
} }
})(); })();
if (messageSent?.error?.message) {
this.logger.error(messageSent.error.message);
throw messageSent.error.message.toString();
}
console.log(content);
const messageRaw: MessageRaw = { const messageRaw: MessageRaw = {
key: { fromMe: true, id: messageSent?.messages[0]?.id, remoteJid: this.createJid(number) }, key: { fromMe: true, id: messageSent?.messages[0]?.id, remoteJid: this.createJid(number) },
//pushName: messageSent.pushName, //pushName: messageSent.pushName,
message: this.convertMessageToRaw(message), message: this.convertMessageToRaw(message, content),
messageType: this.renderMessageType(content.type), messageType: this.renderMessageType(content.type),
messageTimestamp: (messageSent?.messages[0]?.timestamp as number) || Math.round(new Date().getTime() / 1000), messageTimestamp: (messageSent?.messages[0]?.timestamp as number) || Math.round(new Date().getTime() / 1000),
owner: this.instance.name, owner: this.instance.name,
@ -1154,6 +1231,10 @@ export class BusinessStartupService extends WAStartupService {
} }
} }
public async deleteMessage() {
throw new BadRequestException('Method not available on WhatsApp Business API');
}
// methods not available on WhatsApp Business API // methods not available on WhatsApp Business API
public async mediaSticker() { public async mediaSticker() {
throw new BadRequestException('Method not available on WhatsApp Business API'); throw new BadRequestException('Method not available on WhatsApp Business API');
@ -1176,9 +1257,6 @@ export class BusinessStartupService extends WAStartupService {
public async archiveChat() { public async archiveChat() {
throw new BadRequestException('Method not available on WhatsApp Business API'); throw new BadRequestException('Method not available on WhatsApp Business API');
} }
public async deleteMessage() {
throw new BadRequestException('Method not available on WhatsApp Business API');
}
public async fetchProfile() { public async fetchProfile() {
throw new BadRequestException('Method not available on WhatsApp Business API'); throw new BadRequestException('Method not available on WhatsApp Business API');
} }