mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-22 20:12: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)
|
||||
|
||||
### Feature
|
||||
|
@ -406,7 +406,7 @@ export const listMessageSchema: JSONSchema7 = {
|
||||
description: { type: 'string' },
|
||||
rowId: { type: 'string' },
|
||||
},
|
||||
required: ['title', 'description', 'rowId'],
|
||||
required: ['title', 'rowId'],
|
||||
...isNotEmpty('title', 'description', 'rowId'),
|
||||
},
|
||||
},
|
||||
|
@ -10,6 +10,7 @@ export class Session {
|
||||
export class PrefilledVariables {
|
||||
remoteJid?: string;
|
||||
pushName?: string;
|
||||
messageType?: string;
|
||||
additionalData?: { [key: string]: any };
|
||||
}
|
||||
|
||||
|
@ -269,19 +269,27 @@ export class TypebotService {
|
||||
}
|
||||
|
||||
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 = {
|
||||
conversation: msg.conversation,
|
||||
extendedTextMessage: msg.extendedTextMessage?.text,
|
||||
responseRowId: msg.listResponseMessage?.singleSelectReply?.selectedRowId,
|
||||
};
|
||||
|
||||
this.logger.verbose('type message: ' + types);
|
||||
|
||||
return types;
|
||||
const messageType = Object.keys(types).find(key => types[key] !== undefined) || 'unknown';
|
||||
|
||||
this.logger.verbose('Type message: ' + JSON.stringify(types));
|
||||
return { ...types, messageType };
|
||||
}
|
||||
|
||||
|
||||
private getMessageContent(types: any) {
|
||||
this.logger.verbose('get message content');
|
||||
const typeKey = Object.keys(types).find((key) => types[key] !== undefined);
|
||||
@ -305,6 +313,101 @@ export class TypebotService {
|
||||
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) {
|
||||
if (data.remoteJid === 'status@broadcast') return;
|
||||
const id = Math.floor(Math.random() * 10000000000).toString();
|
||||
@ -565,6 +668,7 @@ export class TypebotService {
|
||||
const delay_message = findTypebot.delay_message;
|
||||
const unknown_message = findTypebot.unknown_message;
|
||||
const listening_from_me = findTypebot.listening_from_me;
|
||||
const messageType = this.getTypeMessage(msg.message).messageType;
|
||||
|
||||
const session = sessions.find((session) => session.remoteJid === remoteJid);
|
||||
|
||||
@ -687,6 +791,9 @@ export class TypebotService {
|
||||
sessions: sessions,
|
||||
remoteJid: remoteJid,
|
||||
pushName: msg.pushName,
|
||||
prefilledVariables: {
|
||||
messageType: messageType,
|
||||
},
|
||||
});
|
||||
|
||||
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];
|
||||
let content: any = message.type + 'Message';
|
||||
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;
|
||||
}
|
||||
|
||||
private messageInteractiveJson(received: any) {
|
||||
const message = received.messages[0];
|
||||
const content: any = { conversation: message.interactive[message.interactive.type].title };
|
||||
message.context ? (content.extendedTextMessage = { contextInfo: { stanzaId: message.context.id } }) : content;
|
||||
let content: any = { conversation: message.interactive[message.interactive.type].title };
|
||||
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;
|
||||
}
|
||||
|
||||
@ -198,18 +212,20 @@ export class BusinessStartupService extends WAStartupService {
|
||||
let content: any;
|
||||
const message = received.messages[0];
|
||||
if (message.from === received.metadata.phone_number_id) {
|
||||
content = { extendedTextMessage: { text: message.text.body } };
|
||||
message.context ? (content.extendedTextMessage.contextInfo = { stanzaId: message.context.id }) : content;
|
||||
content = {
|
||||
extendedTextMessage: { text: message.text.body },
|
||||
};
|
||||
message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
private messageContactsJson(received: any) {
|
||||
const message = received.messages[0];
|
||||
const content: any = {};
|
||||
let content: any = {};
|
||||
|
||||
const vcard = (contact: any) => {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -287,8 +303,11 @@ export class BusinessStartupService extends WAStartupService {
|
||||
case 'document':
|
||||
messageType = 'documentMessage';
|
||||
break;
|
||||
case 'template':
|
||||
messageType = 'conversation';
|
||||
break;
|
||||
default:
|
||||
messageType = 'imageMessage';
|
||||
messageType = 'conversation';
|
||||
break;
|
||||
}
|
||||
|
||||
@ -339,6 +358,18 @@ export class BusinessStartupService extends WAStartupService {
|
||||
owner: this.instance.name,
|
||||
// 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) {
|
||||
messageRaw = {
|
||||
key,
|
||||
@ -374,6 +405,7 @@ export class BusinessStartupService extends WAStartupService {
|
||||
this.logger.log(messageRaw);
|
||||
|
||||
this.logger.verbose('Sending data to webhook in event MESSAGES_UPSERT');
|
||||
|
||||
this.sendDataWebhook(Events.MESSAGES_UPSERT, messageRaw);
|
||||
|
||||
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) {
|
||||
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 (content?.context?.message_id) {
|
||||
convertMessage = {
|
||||
imageMessage: message,
|
||||
contextInfo: { stanzaId: content.context.message_id },
|
||||
};
|
||||
return convertMessage;
|
||||
}
|
||||
return {
|
||||
imageMessage: message,
|
||||
};
|
||||
}
|
||||
|
||||
if (message?.mediaType === 'video') {
|
||||
if (content?.context?.message_id) {
|
||||
convertMessage = {
|
||||
videoMessage: message,
|
||||
contextInfo: { stanzaId: content.context.message_id },
|
||||
};
|
||||
return convertMessage;
|
||||
}
|
||||
return {
|
||||
videoMessage: message,
|
||||
};
|
||||
}
|
||||
|
||||
if (message?.mediaType === 'audio') {
|
||||
if (content?.context?.message_id) {
|
||||
convertMessage = {
|
||||
audioMessage: message,
|
||||
contextInfo: { stanzaId: content.context.message_id },
|
||||
};
|
||||
return convertMessage;
|
||||
}
|
||||
return {
|
||||
audioMessage: message,
|
||||
};
|
||||
}
|
||||
|
||||
if (message?.mediaType === 'document') {
|
||||
if (content?.context?.message_id) {
|
||||
convertMessage = {
|
||||
documentMessage: message,
|
||||
contextInfo: { stanzaId: content.context.message_id },
|
||||
};
|
||||
return convertMessage;
|
||||
}
|
||||
return {
|
||||
documentMessage: message,
|
||||
};
|
||||
@ -610,7 +680,6 @@ export class BusinessStartupService extends WAStartupService {
|
||||
message_id: message['reactionMessage']['key']['id'],
|
||||
emoji: message['reactionMessage']['text'],
|
||||
},
|
||||
context: { message_id: quoted.id },
|
||||
};
|
||||
quoted ? (content.context = { message_id: quoted.id }) : content;
|
||||
return await this.post(content, 'messages');
|
||||
@ -670,6 +739,7 @@ export class BusinessStartupService extends WAStartupService {
|
||||
[message['mediaType']]: {
|
||||
[message['type']]: message['id'],
|
||||
preview_url: linkPreview,
|
||||
caption: message['caption'],
|
||||
},
|
||||
};
|
||||
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 = {
|
||||
key: { fromMe: true, id: messageSent?.messages[0]?.id, remoteJid: this.createJid(number) },
|
||||
//pushName: messageSent.pushName,
|
||||
message: this.convertMessageToRaw(message),
|
||||
message: this.convertMessageToRaw(message, content),
|
||||
messageType: this.renderMessageType(content.type),
|
||||
messageTimestamp: (messageSent?.messages[0]?.timestamp as number) || Math.round(new Date().getTime() / 1000),
|
||||
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
|
||||
public async mediaSticker() {
|
||||
throw new BadRequestException('Method not available on WhatsApp Business API');
|
||||
@ -1176,9 +1257,6 @@ export class BusinessStartupService extends WAStartupService {
|
||||
public async archiveChat() {
|
||||
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() {
|
||||
throw new BadRequestException('Method not available on WhatsApp Business API');
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user