mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-26 18:38:39 -06:00
Merge branch 'main' into heroku-button
This commit is contained in:
commit
9e977d45ab
15
CHANGELOG.md
15
CHANGELOG.md
@ -1,4 +1,15 @@
|
||||
# 1.5.1 (homolog)
|
||||
|
||||
# 1.5.2 (2023-09-28 17:56)
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix chatwootSchema in chatwoot model to store reopen_conversation and conversation_pending options
|
||||
* Problem resolved when sending files from minio to typebot
|
||||
* Improvement in the "startTypebot" method to create persistent session when triggered
|
||||
* New manager for Evo 1.5.2 - Set Typebot update
|
||||
* Resolved problems when reading/querying instances
|
||||
|
||||
# 1.5.1 (2023-09-17 13:50)
|
||||
|
||||
### Feature
|
||||
|
||||
@ -7,10 +18,12 @@
|
||||
* Added webhooks for typebot events
|
||||
* Added ChamaAI integration
|
||||
* Added webhook to send errors
|
||||
* Added support for messaging with ads on chatwoot
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix looping connection messages in chatwoot
|
||||
* Improved performance of fetch instances
|
||||
|
||||
# 1.5.0 (2023-08-18 12:47)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
FROM node:16.18-alpine
|
||||
|
||||
LABEL version="1.5.1" description="Api to control whatsapp features through http requests."
|
||||
LABEL version="1.5.2" description="Api to control whatsapp features through http requests."
|
||||
LABEL maintainer="Davidson Gomes" git="https://github.com/DavidsonGomes"
|
||||
LABEL contact="contato@agenciadgcode.com"
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "evolution-api",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.2",
|
||||
"description": "Rest api for communication with WhatsApp",
|
||||
"main": "./dist/src/main.js",
|
||||
"scripts": {
|
||||
@ -43,10 +43,10 @@
|
||||
"dependencies": {
|
||||
"@adiwajshing/keyed-db": "^0.2.4",
|
||||
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
||||
"@figuro/chatwoot-sdk": "^1.1.14",
|
||||
"@figuro/chatwoot-sdk": "^1.1.16",
|
||||
"@hapi/boom": "^10.0.1",
|
||||
"@sentry/node": "^7.59.2",
|
||||
"@whiskeysockets/baileys": "^6.4.1",
|
||||
"@whiskeysockets/baileys": "^6.5.0",
|
||||
"amqplib": "^0.10.3",
|
||||
"axios": "^1.3.5",
|
||||
"class-validator": "^0.13.2",
|
||||
|
@ -76,6 +76,10 @@ export type Websocket = {
|
||||
ENABLED: boolean;
|
||||
};
|
||||
|
||||
export type Chatwoot = {
|
||||
USE_REPLY_ID: boolean;
|
||||
};
|
||||
|
||||
export type EventsWebhook = {
|
||||
APPLICATION_STARTUP: boolean;
|
||||
QRCODE_UPDATED: boolean;
|
||||
@ -145,6 +149,7 @@ export interface Env {
|
||||
QRCODE: QrCode;
|
||||
AUTHENTICATION: Auth;
|
||||
PRODUCTION?: Production;
|
||||
CHATWOOT?: Chatwoot;
|
||||
}
|
||||
|
||||
export type Key = keyof Env;
|
||||
@ -166,11 +171,10 @@ export class ConfigService {
|
||||
? this.envYaml()
|
||||
: this.envProcess();
|
||||
this.env.PRODUCTION = process.env?.NODE_ENV === 'PROD';
|
||||
|
||||
if ((process.env?.DOCKER_ENV === 'true', process.env?.HEROKU_ENV === 'true')) {
|
||||
this.env.SERVER.TYPE = 'http';
|
||||
this.env.SERVER.PORT = parseInt(process.env.PORT) || 8080;
|
||||
}
|
||||
// if ((process.env?.DOCKER_ENV === 'true', process.env?.HEROKU_ENV === 'true')) {
|
||||
// this.env.SERVER.TYPE = 'http';
|
||||
// this.env.SERVER.PORT = parseInt(process.env.PORT) || 8080;
|
||||
// }
|
||||
}
|
||||
|
||||
private envYaml(): Env {
|
||||
@ -250,9 +254,7 @@ export class ConfigService {
|
||||
COLOR: process.env?.LOG_COLOR === 'true',
|
||||
BAILEYS: (process.env?.LOG_BAILEYS as LogBaileys) || 'error',
|
||||
},
|
||||
DEL_INSTANCE: isBooleanString(process.env?.DEL_INSTANCE)
|
||||
? process.env.DEL_INSTANCE === 'true'
|
||||
: Number.parseInt(process.env.DEL_INSTANCE) || false,
|
||||
DEL_INSTANCE: process.env?.DEL_INSTANCE === 'true' ? 5 : Number.parseInt(process.env.DEL_INSTANCE) || false,
|
||||
WEBHOOK: {
|
||||
GLOBAL: {
|
||||
URL: process.env?.WEBHOOK_GLOBAL_URL || '',
|
||||
@ -309,6 +311,9 @@ export class ConfigService {
|
||||
SECRET: process.env.AUTHENTICATION_JWT_SECRET || 'L=0YWt]b2w[WF>#>:&E`',
|
||||
},
|
||||
},
|
||||
CHATWOOT: {
|
||||
USE_REPLY_ID: process.env?.USE_REPLY_ID === 'true',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -156,3 +156,7 @@ AUTHENTICATION:
|
||||
JWT:
|
||||
EXPIRIN_IN: 0 # seconds - 3600s === 1h | zero (0) - never expires
|
||||
SECRET: L=0YWt]b2w[WF>#>:&E`
|
||||
|
||||
# Configure to chatwoot
|
||||
CHATWOOT:
|
||||
USE_REPLY_ID: false
|
||||
|
@ -11,7 +11,7 @@ let io: SocketIO;
|
||||
const cors = configService.get<Cors>('CORS').ORIGIN;
|
||||
|
||||
export const initIO = (httpServer: Server) => {
|
||||
if (configService.get<Websocket>('WEBSOCKET').ENABLED) {
|
||||
if (configService.get<Websocket>('WEBSOCKET')?.ENABLED) {
|
||||
io = new SocketIO(httpServer, {
|
||||
cors: {
|
||||
origin: cors,
|
||||
|
13
src/main.ts
13
src/main.ts
@ -6,7 +6,7 @@ import cors from 'cors';
|
||||
import express, { json, NextFunction, Request, Response, urlencoded } from 'express';
|
||||
import { join } from 'path';
|
||||
|
||||
import { configService, Cors, HttpServer, Rabbitmq, Webhook } from './config/env.config';
|
||||
import { Auth, configService, Cors, HttpServer, Rabbitmq, Webhook } from './config/env.config';
|
||||
import { onUnexpectedError } from './config/error.config';
|
||||
import { Logger } from './config/logger.config';
|
||||
import { ROOT_DIR } from './config/path.config';
|
||||
@ -61,6 +61,8 @@ function bootstrap() {
|
||||
const tzoffset = new Date().getTimezoneOffset() * 60000; //offset in milliseconds
|
||||
const localISOTime = new Date(Date.now() - tzoffset).toISOString();
|
||||
const now = localISOTime;
|
||||
const globalApiKey = configService.get<Auth>('AUTHENTICATION').API_KEY.KEY;
|
||||
const serverUrl = configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
const errorData = {
|
||||
event: 'error',
|
||||
@ -73,6 +75,8 @@ function bootstrap() {
|
||||
},
|
||||
},
|
||||
date_time: now,
|
||||
api_key: globalApiKey,
|
||||
server_url: serverUrl,
|
||||
};
|
||||
|
||||
logger.error(errorData);
|
||||
@ -83,11 +87,6 @@ function bootstrap() {
|
||||
httpService.post('', errorData);
|
||||
}
|
||||
|
||||
if (err['message'].includes('No sessions')) {
|
||||
console.log(err['message']);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return res.status(err['status'] || 500).json({
|
||||
status: err['status'] || 500,
|
||||
error: err['error'] || 'Internal Server Error',
|
||||
@ -125,7 +124,7 @@ function bootstrap() {
|
||||
|
||||
initIO(server);
|
||||
|
||||
if (configService.get<Rabbitmq>('RABBITMQ').ENABLED) initAMQP();
|
||||
if (configService.get<Rabbitmq>('RABBITMQ')?.ENABLED) initAMQP();
|
||||
|
||||
onUnexpectedError();
|
||||
}
|
||||
|
@ -4,6 +4,13 @@ export class Session {
|
||||
status?: string;
|
||||
createdAt?: number;
|
||||
updateAt?: number;
|
||||
prefilledVariables?: PrefilledVariables;
|
||||
}
|
||||
|
||||
export class PrefilledVariables {
|
||||
remoteJid?: string;
|
||||
pushName?: string;
|
||||
additionalData?: { [key: string]: any };
|
||||
}
|
||||
|
||||
export class TypebotDto {
|
||||
|
@ -24,6 +24,8 @@ const chatwootSchema = new Schema<ChatwootRaw>({
|
||||
name_inbox: { type: String, required: true },
|
||||
sign_msg: { type: Boolean, required: true },
|
||||
number: { type: String, required: true },
|
||||
reopen_conversation: { type: Boolean, required: true },
|
||||
conversation_pending: { type: Boolean, required: true },
|
||||
});
|
||||
|
||||
export const ChatwootModel = dbserver?.model(ChatwootRaw.name, chatwootSchema, 'chatwoot');
|
||||
|
@ -20,6 +20,8 @@ export class MessageRaw {
|
||||
messageTimestamp?: number | Long.Long;
|
||||
owner: string;
|
||||
source?: 'android' | 'web' | 'ios';
|
||||
source_id?: string;
|
||||
source_reply_id?: string;
|
||||
}
|
||||
|
||||
const messageSchema = new Schema<MessageRaw>({
|
||||
|
@ -8,6 +8,11 @@ class Session {
|
||||
status?: string;
|
||||
createdAt?: number;
|
||||
updateAt?: number;
|
||||
prefilledVariables?: {
|
||||
remoteJid?: string;
|
||||
pushName?: string;
|
||||
additionalData?: { [key: string]: any };
|
||||
};
|
||||
}
|
||||
|
||||
export class TypebotRaw {
|
||||
@ -40,6 +45,11 @@ const typebotSchema = new Schema<TypebotRaw>({
|
||||
status: { type: String, required: true },
|
||||
createdAt: { type: Number, required: true },
|
||||
updateAt: { type: Number, required: true },
|
||||
prefilledVariables: {
|
||||
remoteJid: { type: String, required: false },
|
||||
pushName: { type: String, required: false },
|
||||
additionalData: { type: Schema.Types.Mixed, required: false }
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -36,8 +36,6 @@ const guards = [instanceExistsGuard, instanceLoggedGuard, authGuard[authType]];
|
||||
|
||||
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||
|
||||
// Hide index if needed
|
||||
|
||||
if (!httpServer.HIDE_INDEX)
|
||||
router.get('/', (req, res) => {
|
||||
res.status(HttpStatus.OK).json({
|
||||
@ -46,13 +44,10 @@ if (!httpServer.HIDE_INDEX)
|
||||
version: packageJson.version,
|
||||
});
|
||||
});
|
||||
|
||||
// Hide manager if needed
|
||||
if (!httpServer.HIDE_MANAGER) router.use('/manager', new ViewsRouter().router);
|
||||
|
||||
router
|
||||
.use('/instance', new InstanceRouter(configService, ...guards).router)
|
||||
.use('/manager', new ViewsRouter().router)
|
||||
.use('/message', new MessageRouter(...guards).router)
|
||||
.use('/chat', new ChatRouter(...guards).router)
|
||||
.use('/group', new GroupRouter(...guards).router)
|
||||
|
@ -2,6 +2,7 @@ import ChatwootClient from '@figuro/chatwoot-sdk';
|
||||
import axios from 'axios';
|
||||
import FormData from 'form-data';
|
||||
import { createReadStream, readFileSync, unlinkSync, writeFileSync } from 'fs';
|
||||
import Jimp from 'jimp';
|
||||
import mimeTypes from 'mime-types';
|
||||
import path from 'path';
|
||||
|
||||
@ -949,7 +950,6 @@ export class ChatwootService {
|
||||
|
||||
public async receiveWebhook(instance: InstanceDto, body: any) {
|
||||
try {
|
||||
// espera 500ms para evitar duplicidade de mensagens
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
|
||||
this.logger.verbose('receive webhook to chatwoot instance: ' + instance.instanceName);
|
||||
@ -1125,6 +1125,20 @@ export class ChatwootService {
|
||||
return result;
|
||||
}
|
||||
|
||||
private getAdsMessage(msg: any) {
|
||||
interface AdsMessage {
|
||||
title: string;
|
||||
body: string;
|
||||
thumbnailUrl: string;
|
||||
sourceUrl: string;
|
||||
}
|
||||
const adsMessage: AdsMessage | undefined = msg.extendedTextMessage?.contextInfo.externalAdReply;
|
||||
|
||||
this.logger.verbose('Get ads message if it exist');
|
||||
adsMessage && this.logger.verbose('Ads message: ' + adsMessage);
|
||||
return adsMessage;
|
||||
}
|
||||
|
||||
private getTypeMessage(msg: any) {
|
||||
this.logger.verbose('get type message');
|
||||
|
||||
@ -1278,15 +1292,17 @@ export class ChatwootService {
|
||||
|
||||
const isMedia = this.isMediaMessage(body.message);
|
||||
|
||||
const adsMessage = this.getAdsMessage(body.message);
|
||||
|
||||
if (!bodyMessage && !isMedia) {
|
||||
this.logger.warn('no body message found');
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.verbose('get conversation in chatwoot');
|
||||
const getConversion = await this.createConversation(instance, body);
|
||||
const getConversation = await this.createConversation(instance, body);
|
||||
|
||||
if (!getConversion) {
|
||||
if (!getConversation) {
|
||||
this.logger.warn('conversation not found');
|
||||
return;
|
||||
}
|
||||
@ -1337,7 +1353,7 @@ export class ChatwootService {
|
||||
}
|
||||
|
||||
this.logger.verbose('send data to chatwoot');
|
||||
const send = await this.sendData(getConversion, fileName, messageType, content);
|
||||
const send = await this.sendData(getConversation, fileName, messageType, content);
|
||||
|
||||
if (!send) {
|
||||
this.logger.warn('message not sent');
|
||||
@ -1358,7 +1374,7 @@ export class ChatwootService {
|
||||
this.logger.verbose('message is not group');
|
||||
|
||||
this.logger.verbose('send data to chatwoot');
|
||||
const send = await this.sendData(getConversion, fileName, messageType, bodyMessage);
|
||||
const send = await this.sendData(getConversation, fileName, messageType, bodyMessage);
|
||||
|
||||
if (!send) {
|
||||
this.logger.warn('message not sent');
|
||||
@ -1378,6 +1394,67 @@ export class ChatwootService {
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose('check if has Ads Message');
|
||||
if (adsMessage) {
|
||||
this.logger.verbose('message is from Ads');
|
||||
|
||||
this.logger.verbose('get base64 from media ads message');
|
||||
const imgBuffer = await axios.get(adsMessage.thumbnailUrl, { responseType: 'arraybuffer' });
|
||||
|
||||
const extension = mimeTypes.extension(imgBuffer.headers['content-type']);
|
||||
const mimeType = extension && mimeTypes.lookup(extension);
|
||||
|
||||
if (!mimeType) {
|
||||
this.logger.warn('mimetype of Ads message not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const random = Math.random().toString(36).substring(7);
|
||||
const nameFile = `${random}.${mimeTypes.extension(mimeType)}`;
|
||||
const fileData = Buffer.from(imgBuffer.data, 'binary');
|
||||
const fileName = `${path.join(waInstance?.storePath, 'temp', `${nameFile}`)}`;
|
||||
|
||||
this.logger.verbose('temp file name: ' + nameFile);
|
||||
this.logger.verbose('create temp file');
|
||||
await Jimp.read(fileData)
|
||||
.then(async (img) => {
|
||||
await img.cover(320, 180).writeAsync(fileName);
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.error(`image is not write: ${err}`);
|
||||
});
|
||||
const truncStr = (str: string, len: number) => {
|
||||
return str.length > len ? str.substring(0, len) + '...' : str;
|
||||
};
|
||||
|
||||
const title = truncStr(adsMessage.title, 40);
|
||||
const description = truncStr(adsMessage.body, 75);
|
||||
|
||||
this.logger.verbose('send data to chatwoot');
|
||||
const send = await this.sendData(
|
||||
getConversation,
|
||||
fileName,
|
||||
messageType,
|
||||
`${bodyMessage}\n\n\n**${title}**\n${description}\n${adsMessage.sourceUrl}`,
|
||||
);
|
||||
|
||||
if (!send) {
|
||||
this.logger.warn('message not sent');
|
||||
return;
|
||||
}
|
||||
|
||||
this.messageCacheFile = path.join(ROOT_DIR, 'store', 'chatwoot', `${instance.instanceName}_cache.txt`);
|
||||
|
||||
this.messageCache = this.loadMessageCache();
|
||||
|
||||
this.messageCache.add(send.id.toString());
|
||||
|
||||
this.logger.verbose('save message cache');
|
||||
this.saveMessageCache();
|
||||
|
||||
return send;
|
||||
}
|
||||
|
||||
this.logger.verbose('check if is group');
|
||||
if (body.key.remoteJid.includes('@g.us')) {
|
||||
this.logger.verbose('message is group');
|
||||
@ -1394,7 +1471,7 @@ export class ChatwootService {
|
||||
}
|
||||
|
||||
this.logger.verbose('send data to chatwoot');
|
||||
const send = await this.createMessage(instance, getConversion, content, messageType);
|
||||
const send = await this.createMessage(instance, getConversation, content, messageType);
|
||||
|
||||
if (!send) {
|
||||
this.logger.warn('message not sent');
|
||||
@ -1415,7 +1492,7 @@ export class ChatwootService {
|
||||
this.logger.verbose('message is not group');
|
||||
|
||||
this.logger.verbose('send data to chatwoot');
|
||||
const send = await this.createMessage(instance, getConversion, bodyMessage, messageType);
|
||||
const send = await this.createMessage(instance, getConversation, bodyMessage, messageType);
|
||||
|
||||
if (!send) {
|
||||
this.logger.warn('message not sent');
|
||||
|
@ -7,6 +7,9 @@ import { join } from 'path';
|
||||
import { Auth, ConfigService, Database, DelInstance, HttpServer, Redis } from '../../config/env.config';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
import { INSTANCE_DIR, STORE_DIR } from '../../config/path.config';
|
||||
// inserido por francis inicio
|
||||
import { NotFoundException } from '../../exceptions';
|
||||
// inserido por francis fim
|
||||
import { dbserver } from '../../libs/db.connect';
|
||||
import { RedisCache } from '../../libs/redis.client';
|
||||
import {
|
||||
@ -72,7 +75,7 @@ export class WAMonitoringService {
|
||||
}, 1000 * 60 * time);
|
||||
}
|
||||
}
|
||||
|
||||
/* ocultado por francis inicio
|
||||
public async instanceInfo(instanceName?: string) {
|
||||
this.logger.verbose('get instance info');
|
||||
|
||||
@ -128,6 +131,96 @@ export class WAMonitoringService {
|
||||
return instances;
|
||||
}
|
||||
|
||||
ocultado por francis fim */
|
||||
|
||||
// inserido por francis inicio
|
||||
|
||||
public async instanceInfo(instanceName?: string) {
|
||||
this.logger.verbose('get instance info');
|
||||
if (instanceName && !this.waInstances[instanceName]) {
|
||||
throw new NotFoundException(`Instance "${instanceName}" not found`);
|
||||
}
|
||||
|
||||
const instances: any[] = [];
|
||||
|
||||
for await (const [key, value] of Object.entries(this.waInstances)) {
|
||||
if (value) {
|
||||
this.logger.verbose('get instance info: ' + key);
|
||||
let chatwoot: any;
|
||||
|
||||
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
const findChatwoot = await this.waInstances[key].findChatwoot();
|
||||
|
||||
if (findChatwoot && findChatwoot.enabled) {
|
||||
chatwoot = {
|
||||
...findChatwoot,
|
||||
webhook_url: `${urlServer}/chatwoot/webhook/${encodeURIComponent(key)}`,
|
||||
};
|
||||
}
|
||||
|
||||
if (value.connectionStatus.state === 'open') {
|
||||
this.logger.verbose('instance: ' + key + ' - connectionStatus: open');
|
||||
|
||||
const instanceData = {
|
||||
instance: {
|
||||
instanceName: key,
|
||||
owner: value.wuid,
|
||||
profileName: (await value.getProfileName()) || 'not loaded',
|
||||
profilePictureUrl: value.profilePictureUrl,
|
||||
profileStatus: (await value.getProfileStatus()) || '',
|
||||
status: value.connectionStatus.state,
|
||||
},
|
||||
};
|
||||
|
||||
if (this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES) {
|
||||
instanceData.instance['serverUrl'] = this.configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
instanceData.instance['apikey'] = (await this.repository.auth.find(key)).apikey;
|
||||
|
||||
instanceData.instance['chatwoot'] = chatwoot;
|
||||
}
|
||||
|
||||
instances.push(instanceData);
|
||||
} else {
|
||||
this.logger.verbose('instance: ' + key + ' - connectionStatus: ' + value.connectionStatus.state);
|
||||
|
||||
const instanceData = {
|
||||
instance: {
|
||||
instanceName: key,
|
||||
status: value.connectionStatus.state,
|
||||
},
|
||||
};
|
||||
|
||||
if (this.configService.get<Auth>('AUTHENTICATION').EXPOSE_IN_FETCH_INSTANCES) {
|
||||
instanceData.instance['serverUrl'] = this.configService.get<HttpServer>('SERVER').URL;
|
||||
|
||||
instanceData.instance['apikey'] = (await this.repository.auth.find(key)).apikey;
|
||||
|
||||
instanceData.instance['chatwoot'] = chatwoot;
|
||||
}
|
||||
|
||||
instances.push(instanceData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose('return instance info: ' + instances.length);
|
||||
|
||||
return instances.find((i) => i.instance.instanceName === instanceName) ?? instances;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// inserido por francis fim
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private delInstanceFiles() {
|
||||
this.logger.verbose('cron to delete instance files started');
|
||||
setInterval(async () => {
|
||||
|
@ -100,6 +100,13 @@ export class TypebotService {
|
||||
const url = data.url;
|
||||
const typebot = data.typebot;
|
||||
const variables = data.variables;
|
||||
const findTypebot = await this.find(instance);
|
||||
const sessions = (findTypebot.sessions as Session[]) ?? [];
|
||||
const expire = findTypebot.expire;
|
||||
const keyword_finish = findTypebot.keyword_finish;
|
||||
const delay_message = findTypebot.delay_message;
|
||||
const unknown_message = findTypebot.unknown_message;
|
||||
const listening_from_me = findTypebot.listening_from_me;
|
||||
|
||||
const prefilledVariables = {
|
||||
remoteJid: remoteJid,
|
||||
@ -109,33 +116,38 @@ export class TypebotService {
|
||||
prefilledVariables[variable.name] = variable.value;
|
||||
});
|
||||
|
||||
const id = Math.floor(Math.random() * 10000000000).toString();
|
||||
|
||||
const reqData = {
|
||||
sessionId: id,
|
||||
startParams: {
|
||||
typebot: data.typebot,
|
||||
const response = await this.createNewSession(instance, {
|
||||
url: url,
|
||||
typebot: typebot,
|
||||
remoteJid: remoteJid,
|
||||
expire: expire,
|
||||
keyword_finish: keyword_finish,
|
||||
delay_message: delay_message,
|
||||
unknown_message: unknown_message,
|
||||
listening_from_me: listening_from_me,
|
||||
sessions: sessions,
|
||||
prefilledVariables: prefilledVariables,
|
||||
},
|
||||
};
|
||||
|
||||
const request = await axios.post(data.url + '/api/v1/sendMessage', reqData);
|
||||
});
|
||||
|
||||
if (response.sessionId) {
|
||||
await this.sendWAMessage(
|
||||
instance,
|
||||
remoteJid,
|
||||
request.data.messages,
|
||||
request.data.input,
|
||||
request.data.clientSideActions,
|
||||
response.messages,
|
||||
response.input,
|
||||
response.clientSideActions,
|
||||
);
|
||||
|
||||
this.waMonitor.waInstances[instance.instanceName].sendDataWebhook(Events.TYPEBOT_START, {
|
||||
remoteJid: remoteJid,
|
||||
url: url,
|
||||
typebot: typebot,
|
||||
variables: variables,
|
||||
sessionId: id,
|
||||
prefilledVariables: prefilledVariables,
|
||||
sessionId: `${response.sessionId}`,
|
||||
});
|
||||
} else {
|
||||
throw new Error("Session ID not found in response");
|
||||
}
|
||||
|
||||
return {
|
||||
typebot: {
|
||||
@ -144,7 +156,7 @@ export class TypebotService {
|
||||
url: url,
|
||||
remoteJid: remoteJid,
|
||||
typebot: typebot,
|
||||
variables: variables,
|
||||
prefilledVariables: prefilledVariables,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -193,8 +205,9 @@ export class TypebotService {
|
||||
startParams: {
|
||||
typebot: data.typebot,
|
||||
prefilledVariables: {
|
||||
...data.prefilledVariables,
|
||||
remoteJid: data.remoteJid,
|
||||
pushName: data.pushName,
|
||||
pushName: data.pushName || 'Default Name',
|
||||
instanceName: instance.instanceName,
|
||||
},
|
||||
},
|
||||
@ -209,6 +222,12 @@ export class TypebotService {
|
||||
status: 'opened',
|
||||
createdAt: Date.now(),
|
||||
updateAt: Date.now(),
|
||||
prefilledVariables: {
|
||||
...data.prefilledVariables,
|
||||
remoteJid: data.remoteJid,
|
||||
pushName: data.pushName || 'Default Name',
|
||||
instanceName: instance.instanceName,
|
||||
}
|
||||
});
|
||||
|
||||
const typebotData = {
|
||||
|
@ -654,15 +654,17 @@ export class WAStartupService {
|
||||
const amqp = getAMQP();
|
||||
|
||||
if (amqp) {
|
||||
this.logger.verbose('Sending data to rabbitMQ on channel: ' + this.instance.name);
|
||||
if (Array.isArray(rabbitmqLocal) && rabbitmqLocal.includes(we)) {
|
||||
const exchangeName = this.instanceName ?? 'evolution_exchange';
|
||||
this.logger.verbose('Sending data to rabbitMQ on event: ' + event);
|
||||
const exchangeName = this.instance.name ?? 'evolution_exchange';
|
||||
|
||||
amqp.assertExchange(exchangeName, 'topic', {
|
||||
durable: true,
|
||||
autoDelete: false,
|
||||
});
|
||||
|
||||
const queueName = `${this.instanceName}.${event}`;
|
||||
const queueName = `${this.instance.name}.${event}`;
|
||||
|
||||
amqp.assertQueue(queueName, {
|
||||
durable: true,
|
||||
@ -711,7 +713,7 @@ export class WAStartupService {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.configService.get<Websocket>('WEBSOCKET').ENABLED && this.localWebsocket.enabled) {
|
||||
if (this.configService.get<Websocket>('WEBSOCKET')?.ENABLED && this.localWebsocket.enabled) {
|
||||
this.logger.verbose('Sending data to websocket on channel: ' + this.instance.name);
|
||||
if (Array.isArray(websocketLocal) && websocketLocal.includes(we)) {
|
||||
this.logger.verbose('Sending data to websocket on event: ' + event);
|
||||
@ -1434,8 +1436,9 @@ export class WAStartupService {
|
||||
|
||||
if (
|
||||
type !== 'notify' ||
|
||||
!received.message ||
|
||||
!received?.message ||
|
||||
received.message?.protocolMessage ||
|
||||
received.message.senderKeyDistributionMessage ||
|
||||
received.message?.pollUpdateMessage
|
||||
) {
|
||||
this.logger.verbose('message rejected');
|
||||
@ -1954,9 +1957,10 @@ export class WAStartupService {
|
||||
private async sendMessageWithTyping<T = proto.IMessage>(number: string, message: T, options?: Options) {
|
||||
this.logger.verbose('Sending message with typing');
|
||||
|
||||
const numberWA = await this.whatsappNumber({ numbers: [number] });
|
||||
const isWA = numberWA[0];
|
||||
this.logger.verbose(`Check if number "${number}" is WhatsApp`);
|
||||
const isWA = (await this.whatsappNumber({ numbers: [number] }))?.shift();
|
||||
|
||||
this.logger.verbose(`Exists: "${isWA.exists}" | jid: ${isWA.jid}`);
|
||||
if (!isWA.exists && !isJidGroup(isWA.jid) && !isWA.jid.includes('@broadcast')) {
|
||||
throw new BadRequestException(isWA);
|
||||
}
|
||||
@ -1980,7 +1984,7 @@ export class WAStartupService {
|
||||
this.logger.verbose('Sending presence update: paused');
|
||||
}
|
||||
|
||||
const linkPreview = options?.linkPreview != false ? undefined : false;
|
||||
const linkPreview = options?.linkPreview == true ? undefined : options?.linkPreview || false;
|
||||
|
||||
let quoted: WAMessage;
|
||||
|
||||
@ -2000,9 +2004,9 @@ export class WAStartupService {
|
||||
let mentions: string[];
|
||||
if (isJidGroup(sender)) {
|
||||
try {
|
||||
const groupMetadata = await this.client.groupMetadata(sender);
|
||||
const group = await this.findGroup({ groupJid: sender }, 'inner');
|
||||
|
||||
if (!groupMetadata) {
|
||||
if (!group) {
|
||||
throw new NotFoundException('Group not found');
|
||||
}
|
||||
|
||||
@ -2013,7 +2017,7 @@ export class WAStartupService {
|
||||
this.logger.verbose('Mentions everyone');
|
||||
|
||||
this.logger.verbose('Getting group metadata');
|
||||
mentions = groupMetadata.participants.map((participant) => participant.id);
|
||||
mentions = group.participants.map((participant) => participant.id);
|
||||
this.logger.verbose('Getting group metadata for mentions');
|
||||
} else if (options.mentions?.mentioned?.length) {
|
||||
this.logger.verbose('Mentions manually defined');
|
||||
@ -2021,7 +2025,6 @@ export class WAStartupService {
|
||||
const jid = this.createJid(mention);
|
||||
if (isJidGroup(jid)) {
|
||||
return null;
|
||||
// throw new BadRequestException('Mentions must be a number');
|
||||
}
|
||||
return jid;
|
||||
});
|
||||
@ -2307,22 +2310,36 @@ export class WAStartupService {
|
||||
mediaMessage.fileName = arrayMatch[1];
|
||||
this.logger.verbose('File name: ' + mediaMessage.fileName);
|
||||
}
|
||||
// *inserido francis inicio
|
||||
let mimetype: string;
|
||||
// *inserido francis final
|
||||
|
||||
|
||||
if (mediaMessage.mediatype === 'image' && !mediaMessage.fileName) {
|
||||
mediaMessage.fileName = 'image.png';
|
||||
// inserido francis inicio
|
||||
mimetype = 'image/png';
|
||||
// inserido francis inicio
|
||||
|
||||
}
|
||||
|
||||
if (mediaMessage.mediatype === 'video' && !mediaMessage.fileName) {
|
||||
mediaMessage.fileName = 'video.mp4';
|
||||
// inserido francis inicio
|
||||
mimetype = 'video/mp4';
|
||||
// inserido francis final
|
||||
}
|
||||
|
||||
let mimetype: string;
|
||||
// ocultado francis inicio
|
||||
// let mimetype: string;
|
||||
|
||||
if (isURL(mediaMessage.media)) {
|
||||
mimetype = getMIMEType(mediaMessage.media);
|
||||
} else {
|
||||
mimetype = getMIMEType(mediaMessage.fileName);
|
||||
}
|
||||
|
||||
// if (isURL(mediaMessage.media)) {
|
||||
// mimetype = getMIMEType(mediaMessage.media);
|
||||
// } else {
|
||||
// mimetype = getMIMEType(mediaMessage.fileName);
|
||||
// }
|
||||
// ocultado francis final
|
||||
|
||||
this.logger.verbose('Mimetype: ' + mimetype);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user