mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-23 04:22:02 -06:00
Merge branch 'release/1.7.1'
This commit is contained in:
commit
128119d494
11
CHANGELOG.md
11
CHANGELOG.md
@ -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
|
||||||
|
@ -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'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -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 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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');
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user