Compare commits

...

20 Commits
1.4.0 ... 1.4.2

Author SHA1 Message Date
Davidson Gomes
f95f3126c3 Merge branch 'release/1.4.2' 2023-07-24 20:52:46 -03:00
Davidson Gomes
4d9ca4b451 version: 1.4.2 2023-07-24 20:52:34 -03:00
Davidson Gomes
c76334a68a fix: Ajusts in sticker message to chatwoot 2023-07-24 20:32:29 -03:00
Davidson Gomes
f475391ba6 fix: Ajusts in sticker message to chatwoot 2023-07-24 20:32:15 -03:00
Davidson Gomes
b77f22790b fix: Fixed validation is set settings 2023-07-24 20:13:18 -03:00
Davidson Gomes
757a578c6e Merge branch 'develop' of github.com:EvolutionAPI/evolution-api into develop 2023-07-24 20:12:51 -03:00
Davidson Gomes
c5824767c8 fix: Fixed validation is set settings 2023-07-24 20:11:49 -03:00
Davidson Gomes
84f3f07279 fix: Fixed validation is set settings 2023-07-24 20:11:15 -03:00
Davidson Gomes
f8e1892eee fix: group validation
Group validation
2023-07-24 20:08:24 -03:00
Davidson Gomes
036a8edca0 fix: Promote All Participants in Create Group
Promote All Participants in Create Group
2023-07-24 20:07:05 -03:00
Alan Mosko
58ed6f395f Validação de Grupo 2023-07-24 19:59:09 -03:00
Alan Mosko
ef4be6a612 Start 2023-07-24 19:53:03 -03:00
Davidson Gomes
3d8e6f4394 fix: Fixed mentions
Fixed mentions
2023-07-24 19:08:39 -03:00
Alan Mosko
0cc1f18a7e [BUG] Correção de mencionar
Caso seja enviado everyOne como false sem passar nada no mentioned
2023-07-24 19:05:32 -03:00
Davidson Gomes
8b6e577b8f Merge tag '1.4.1' into develop
* Fixed reconnect with pairing code or qrcode
* Fixed problem in createJid
2023-07-24 18:28:57 -03:00
Davidson Gomes
cc91f2e5db Merge branch 'release/1.4.1' 2023-07-24 18:28:45 -03:00
Davidson Gomes
8d1f2313ac version: 1.4.1 2023-07-24 18:28:39 -03:00
Davidson Gomes
f9abd90cc9 fix: connection state 2023-07-24 18:28:01 -03:00
Davidson Gomes
f7293255cf fix: Fixed reconnect with pairing code or qrcode 2023-07-24 18:21:11 -03:00
Davidson Gomes
7d6a130cf9 Merge tag '1.4.0' into develop
* Added connection functionality via pairing code
* Added fetch profile endpoint in chat controller
* Created settings controller
* Added reject call and send text message when receiving a call
* Added setting to ignore group messages
* Added connection with pairing code in chatwoot with command /init:{NUMBER}
* Added encoding option in endpoint sendWhatsAppAudio

* Added link preview option in send text message
* Fixed problem with fileSha256 appearing when sending a sticker in chatwoot
* Fixed issue where it was not possible to open a conversation when sent at first by me on my cell phone in chatwoot
* Now it only updates the contact name if it is the same as the phone number in chatwoot
* Now accepts all chatwoot inbox templates
* Command to create new instances set to /new_instance:{NAME}:{NUMBER}
* Fix in chatwoot set, sign msg can now be disabled

- Chatwoot: v2.18.0 - v3.0.0 (Beta)
2023-07-24 17:05:43 -03:00
9 changed files with 193 additions and 168 deletions

View File

@@ -1,3 +1,18 @@
# 1.4.2 (2023-07-24 20:52)
### Fixed
* Fixed validation is set settings
* Adjusts in group validations
* Ajusts in sticker message to chatwoot
# 1.4.1 (2023-07-24 18:28)
### Fixed
* Fixed reconnect with pairing code or qrcode
* Fixed problem in createJid
# 1.4.0 (2023-07-24 17:03) # 1.4.0 (2023-07-24 17:03)
### Features ### Features

View File

@@ -1,6 +1,6 @@
{ {
"name": "evolution-api", "name": "evolution-api",
"version": "1.4.0", "version": "1.4.2",
"description": "Rest api for communication with WhatsApp", "description": "Rest api for communication with WhatsApp",
"main": "./dist/src/main.js", "main": "./dist/src/main.js",
"scripts": { "scripts": {

View File

@@ -124,7 +124,6 @@ const optionsSchema: JSONSchema7 = {
const numberDefinition: JSONSchema7Definition = { const numberDefinition: JSONSchema7Definition = {
type: 'string', type: 'string',
// pattern: '^\\d+[\\.@\\w-]+',
description: 'Invalid format', description: 'Invalid format',
}; };
@@ -446,7 +445,6 @@ export const whatsappNumberSchema: JSONSchema7 = {
uniqueItems: true, uniqueItems: true,
items: { items: {
type: 'string', type: 'string',
// pattern: '^\\d+',
description: '"numbers" must be an array of numeric strings', description: '"numbers" must be an array of numeric strings',
}, },
}, },
@@ -669,6 +667,7 @@ export const createGroupSchema: JSONSchema7 = {
subject: { type: 'string' }, subject: { type: 'string' },
description: { type: 'string' }, description: { type: 'string' },
profilePicture: { type: 'string' }, profilePicture: { type: 'string' },
promoteParticipants: { type: 'boolean', enum: [true, false] },
participants: { participants: {
type: 'array', type: 'array',
minItems: 1, minItems: 1,

View File

@@ -41,6 +41,7 @@ export class InstanceController {
chatwoot_url, chatwoot_url,
chatwoot_sign_msg, chatwoot_sign_msg,
}: InstanceDto) { }: InstanceDto) {
try {
this.logger.verbose('requested createInstance from ' + instanceName + ' instance'); this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
if (instanceName !== instanceName.toLowerCase().replace(/[^a-z0-9]/g, '')) { if (instanceName !== instanceName.toLowerCase().replace(/[^a-z0-9]/g, '')) {
@@ -107,7 +108,7 @@ export class InstanceController {
if (qrcode) { if (qrcode) {
this.logger.verbose('creating qrcode'); this.logger.verbose('creating qrcode');
await instance.connectToWhatsapp(number); await instance.connectToWhatsapp(number);
await delay(3000); await delay(5000);
getQrcode = instance.qrCode; getQrcode = instance.qrCode;
} }
@@ -189,6 +190,10 @@ export class InstanceController {
webhook_url: `${urlServer}/chatwoot/webhook/${instance.instanceName}`, webhook_url: `${urlServer}/chatwoot/webhook/${instance.instanceName}`,
}, },
}; };
} catch (error) {
console.log(error);
return { error: true, message: error.toString() };
}
} }
public async connectToWhatsapp({ instanceName, number = null }: InstanceDto) { public async connectToWhatsapp({ instanceName, number = null }: InstanceDto) {
@@ -214,7 +219,7 @@ export class InstanceController {
this.logger.verbose('connecting'); this.logger.verbose('connecting');
await instance.connectToWhatsapp(number); await instance.connectToWhatsapp(number);
await delay(2000); await delay(5000);
return instance.qrCode; return instance.qrCode;
} }
@@ -245,7 +250,12 @@ export class InstanceController {
public async connectionState({ instanceName }: InstanceDto) { public async connectionState({ instanceName }: InstanceDto) {
this.logger.verbose('requested connectionState from ' + instanceName + ' instance'); this.logger.verbose('requested connectionState from ' + instanceName + ' instance');
return this.waMonitor.waInstances[instanceName]?.connectionStatus; return {
instance: {
instanceName: instanceName,
state: this.waMonitor.waInstances[instanceName]?.connectionStatus?.state,
},
};
} }
public async fetchInstances({ instanceName }: InstanceDto) { public async fetchInstances({ instanceName }: InstanceDto) {
@@ -260,9 +270,9 @@ export class InstanceController {
public async logout({ instanceName }: InstanceDto) { public async logout({ instanceName }: InstanceDto) {
this.logger.verbose('requested logout from ' + instanceName + ' instance'); this.logger.verbose('requested logout from ' + instanceName + ' instance');
const stateConn = await this.connectionState({ instanceName }); const { instance } = await this.connectionState({ instanceName });
if (stateConn.state === 'close') { if (instance.state === 'close') {
throw new BadRequestException( throw new BadRequestException(
'The "' + instanceName + '" instance is not connected', 'The "' + instanceName + '" instance is not connected',
); );
@@ -285,15 +295,15 @@ export class InstanceController {
public async deleteInstance({ instanceName }: InstanceDto) { public async deleteInstance({ instanceName }: InstanceDto) {
this.logger.verbose('requested deleteInstance from ' + instanceName + ' instance'); this.logger.verbose('requested deleteInstance from ' + instanceName + ' instance');
const stateConn = await this.connectionState({ instanceName }); const { instance } = await this.connectionState({ instanceName });
if (stateConn.state === 'open') { if (instance.state === 'open') {
throw new BadRequestException( throw new BadRequestException(
'The "' + instanceName + '" instance needs to be disconnected', 'The "' + instanceName + '" instance needs to be disconnected',
); );
} }
try { try {
if (stateConn.state === 'connecting') { if (instance.state === 'connecting') {
this.logger.verbose('logging out instance: ' + instanceName); this.logger.verbose('logging out instance: ' + instanceName);
await this.logout({ instanceName }); await this.logout({ instanceName });

View File

@@ -15,10 +15,6 @@ export class SettingsController {
'requested createSettings from ' + instance.instanceName + ' instance', 'requested createSettings from ' + instance.instanceName + ' instance',
); );
if (data.reject_call && data.msg_call.trim() == '') {
throw new BadRequestException('msg_call is required');
}
return this.settingsService.create(instance, data); return this.settingsService.create(instance, data);
} }

View File

@@ -1,7 +1,8 @@
export class CreateGroupDto { export class CreateGroupDto {
subject: string; subject: string;
description?: string;
participants: string[]; participants: string[];
description?: string;
promoteParticipants?: boolean;
} }
export class GroupPictureDto { export class GroupPictureDto {

View File

@@ -102,7 +102,12 @@ export class RepositoryBroker {
this.logger.verbose('creating store path: ' + storePath); this.logger.verbose('creating store path: ' + storePath);
const tempDir = join(storePath, 'temp'); const tempDir = join(storePath, 'temp');
const chatwootDir = join(storePath, 'chatwoot');
if (!fs.existsSync(chatwootDir)) {
this.logger.verbose('creating chatwoot dir: ' + chatwootDir);
fs.mkdirSync(chatwootDir, { recursive: true });
}
if (!fs.existsSync(tempDir)) { if (!fs.existsSync(tempDir)) {
this.logger.verbose('creating temp dir: ' + tempDir); this.logger.verbose('creating temp dir: ' + tempDir);
fs.mkdirSync(tempDir, { recursive: true }); fs.mkdirSync(tempDir, { recursive: true });

View File

@@ -1179,7 +1179,7 @@ export class ChatwootService {
videoMessage: msg.videoMessage?.caption, videoMessage: msg.videoMessage?.caption,
extendedTextMessage: msg.extendedTextMessage?.text, extendedTextMessage: msg.extendedTextMessage?.text,
messageContextInfo: msg.messageContextInfo?.stanzaId, messageContextInfo: msg.messageContextInfo?.stanzaId,
stickerMessage: msg.stickerMessage?.fileSha256.toString('base64'), stickerMessage: undefined,
documentMessage: msg.documentMessage?.caption, documentMessage: msg.documentMessage?.caption,
documentWithCaptionMessage: documentWithCaptionMessage:
msg.documentWithCaptionMessage?.message?.documentMessage?.caption, msg.documentWithCaptionMessage?.message?.documentMessage?.caption,
@@ -1199,10 +1199,6 @@ export class ChatwootService {
const result = typeKey ? types[typeKey] : undefined; const result = typeKey ? types[typeKey] : undefined;
if (typeKey === 'stickerMessage') {
return null;
}
if (typeKey === 'contactMessage') { if (typeKey === 'contactMessage') {
const vCardData = result.split('\n'); const vCardData = result.split('\n');
const contactInfo = {}; const contactInfo = {};

View File

@@ -116,16 +116,15 @@ import { useMultiFileAuthStateDb } from '../../utils/use-multi-file-auth-state-d
import Long from 'long'; import Long from 'long';
import { WebhookRaw } from '../models/webhook.model'; import { WebhookRaw } from '../models/webhook.model';
import { ChatwootRaw } from '../models/chatwoot.model'; import { ChatwootRaw } from '../models/chatwoot.model';
import { SettingsRaw } from '../models';
import { dbserver } from '../../db/db.connect'; import { dbserver } from '../../db/db.connect';
import NodeCache from 'node-cache'; import NodeCache from 'node-cache';
import { useMultiFileAuthStateRedisDb } from '../../utils/use-multi-file-auth-state-redis-db'; import { useMultiFileAuthStateRedisDb } from '../../utils/use-multi-file-auth-state-redis-db';
import sharp from 'sharp'; import sharp from 'sharp';
import { RedisCache } from '../../db/redis.client'; import { RedisCache } from '../../db/redis.client';
import { Log } from '../../config/env.config'; import { Log } from '../../config/env.config';
import ProxyAgent from 'proxy-agent';
import { ChatwootService } from './chatwoot.service'; import { ChatwootService } from './chatwoot.service';
import { waMonitor } from '../whatsapp.module'; import { waMonitor } from '../whatsapp.module';
import { SettingsRaw } from '../models';
export class WAStartupService { export class WAStartupService {
constructor( constructor(
@@ -382,7 +381,7 @@ export class WAStartupService {
if (!data) { if (!data) {
this.logger.verbose('Settings not found'); this.logger.verbose('Settings not found');
throw new NotFoundException('Settings not found'); return null;
} }
this.logger.verbose(`Settings url: ${data.reject_call}`); this.logger.verbose(`Settings url: ${data.reject_call}`);
@@ -606,11 +605,14 @@ export class WAStartupService {
color: { light: '#ffffff', dark: '#198754' }, color: { light: '#ffffff', dark: '#198754' },
}; };
console.log(this.phoneNumber);
if (this.phoneNumber) { if (this.phoneNumber) {
await delay(2000); await delay(2000);
this.instance.qrcode.pairingCode = await this.client.requestPairingCode( this.instance.qrcode.pairingCode = await this.client.requestPairingCode(
this.phoneNumber, this.phoneNumber,
); );
} else {
this.instance.qrcode.pairingCode = null;
} }
this.logger.verbose('Generating QR code'); this.logger.verbose('Generating QR code');
@@ -894,13 +896,6 @@ export class WAStartupService {
this.phoneNumber = number; this.phoneNumber = number;
// if (number) {
// this.logger.verbose('creating pairing code');
// await delay(5000);
// this.phoneNumber = number;
// this.instance.qrcode.pairingCode = await this.client.requestPairingCode(number);
// }
return this.client; return this.client;
} catch (error) { } catch (error) {
this.logger.error(error); this.logger.error(error);
@@ -1133,7 +1128,7 @@ export class WAStartupService {
received.messageTimestamp = received.messageTimestamp?.toNumber(); received.messageTimestamp = received.messageTimestamp?.toNumber();
} }
if (settings.groups_ignore && received.key.remoteJid.includes('@g.us')) { if (settings?.groups_ignore && received.key.remoteJid.includes('@g.us')) {
this.logger.verbose('group ignored'); this.logger.verbose('group ignored');
return; return;
} }
@@ -1529,6 +1524,12 @@ export class WAStartupService {
number = number.replace(/\D/g, ''); number = number.replace(/\D/g, '');
if (number.length >= 18) {
this.logger.verbose('Jid created is group: ' + `${number}@g.us`);
number = number.replace(/[^\d-]/g, '');
return `${number}@g.us`;
}
this.logger.verbose('Jid created is whatsapp: ' + `${number}@s.whatsapp.net`); this.logger.verbose('Jid created is whatsapp: ' + `${number}@s.whatsapp.net`);
return `${number}@s.whatsapp.net`; return `${number}@s.whatsapp.net`;
} }
@@ -1690,20 +1691,13 @@ export class WAStartupService {
if (options?.mentions) { if (options?.mentions) {
this.logger.verbose('Mentions defined'); this.logger.verbose('Mentions defined');
if ( if (options.mentions?.everyOne) {
!Array.isArray(options.mentions.mentioned) &&
!options.mentions.everyOne
) {
throw new BadRequestException('Mentions must be an array');
}
if (options.mentions.everyOne) {
this.logger.verbose('Mentions everyone'); this.logger.verbose('Mentions everyone');
this.logger.verbose('Getting group metadata'); this.logger.verbose('Getting group metadata');
mentions = groupMetadata.participants.map((participant) => participant.id); mentions = groupMetadata.participants.map((participant) => participant.id);
this.logger.verbose('Getting group metadata for mentions'); this.logger.verbose('Getting group metadata for mentions');
} else { } else if (options.mentions?.mentioned?.length) {
this.logger.verbose('Mentions manually defined'); this.logger.verbose('Mentions manually defined');
mentions = options.mentions.mentioned.map((mention) => { mentions = options.mentions.mentioned.map((mention) => {
const jid = this.createJid(mention); const jid = this.createJid(mention);
@@ -2786,10 +2780,19 @@ export class WAStartupService {
await this.client.groupUpdateDescription(id, create.description); await this.client.groupUpdateDescription(id, create.description);
} }
if (create?.promoteParticipants) {
this.logger.verbose('Prometing group participants: ' + create.description);
await this.updateGParticipant({
groupJid: id,
action: 'promote',
participants: participants,
});
}
const group = await this.client.groupMetadata(id); const group = await this.client.groupMetadata(id);
this.logger.verbose('Getting group metadata'); this.logger.verbose('Getting group metadata');
return { groupMetadata: group }; return group;
} catch (error) { } catch (error) {
this.logger.error(error); this.logger.error(error);
throw new InternalServerErrorException('Error creating group', error.toString()); throw new InternalServerErrorException('Error creating group', error.toString());