feat: Added Typebot integration

This commit is contained in:
Davidson Gomes 2023-08-07 18:54:12 -03:00
parent 7c5d94c19e
commit b502ebd23a
12 changed files with 98 additions and 26 deletions

View File

@ -31,7 +31,7 @@ CLEAN_STORE_CONTACTS=true
CLEAN_STORE_CHATS=true CLEAN_STORE_CHATS=true
# Permanent data storage # Permanent data storage
DATABASE_ENABLED=true DATABASE_ENABLED=false
DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true
DATABASE_CONNECTION_DB_PREFIX_NAME=evdocker DATABASE_CONNECTION_DB_PREFIX_NAME=evdocker
@ -42,13 +42,15 @@ DATABASE_SAVE_MESSAGE_UPDATE=false
DATABASE_SAVE_DATA_CONTACTS=false DATABASE_SAVE_DATA_CONTACTS=false
DATABASE_SAVE_DATA_CHATS=false DATABASE_SAVE_DATA_CHATS=false
REDIS_ENABLED=true REDIS_ENABLED=false
REDIS_URI=redis://redis:6379 REDIS_URI=redis://redis:6379
REDIS_PREFIX_KEY=evdocker REDIS_PREFIX_KEY=evdocker
RABBITMQ_ENABLED=true RABBITMQ_ENABLED=false
RABBITMQ_URI=amqp://guest:guest@rabbitmq:5672 RABBITMQ_URI=amqp://guest:guest@rabbitmq:5672
WEBSOCKET_ENABLED=false
# Global Webhook Settings # Global Webhook Settings
# Each instance's Webhook URL and events will be requested at the time it is created # Each instance's Webhook URL and events will be requested at the time it is created
## Define a global webhook that will listen for enabled events from all instances ## Define a global webhook that will listen for enabled events from all instances

View File

@ -54,6 +54,8 @@ ENV REDIS_PREFIX_KEY=evolution
ENV RABBITMQ_ENABLED=false ENV RABBITMQ_ENABLED=false
ENV RABBITMQ_URI=amqp://guest:guest@rabbitmq:5672 ENV RABBITMQ_URI=amqp://guest:guest@rabbitmq:5672
ENV WEBSOCKET_ENABLED=false
ENV WEBHOOK_GLOBAL_URL= ENV WEBHOOK_GLOBAL_URL=
ENV WEBHOOK_GLOBAL_ENABLED=false ENV WEBHOOK_GLOBAL_ENABLED=false

View File

@ -66,6 +66,10 @@ export type Rabbitmq = {
URI: string; URI: string;
}; };
export type Websocket = {
ENABLED: boolean;
};
export type EventsWebhook = { export type EventsWebhook = {
APPLICATION_STARTUP: boolean; APPLICATION_STARTUP: boolean;
QRCODE_UPDATED: boolean; QRCODE_UPDATED: boolean;
@ -122,6 +126,7 @@ export interface Env {
DATABASE: Database; DATABASE: Database;
REDIS: Redis; REDIS: Redis;
RABBITMQ: Rabbitmq; RABBITMQ: Rabbitmq;
WEBSOCKET: Websocket;
LOG: Log; LOG: Log;
DEL_INSTANCE: DelInstance; DEL_INSTANCE: DelInstance;
WEBHOOK: Webhook; WEBHOOK: Webhook;
@ -211,6 +216,9 @@ export class ConfigService {
ENABLED: process.env?.RABBITMQ_ENABLED === 'true', ENABLED: process.env?.RABBITMQ_ENABLED === 'true',
URI: process.env.RABBITMQ_URI, URI: process.env.RABBITMQ_URI,
}, },
WEBSOCKET: {
ENABLED: process.env?.WEBSOCKET_ENABLED === 'true',
},
LOG: { LOG: {
LEVEL: process.env?.LOG_LEVEL.split(',') as LogLevel[], LEVEL: process.env?.LOG_LEVEL.split(',') as LogLevel[],
COLOR: process.env?.LOG_COLOR === 'true', COLOR: process.env?.LOG_COLOR === 'true',

View File

@ -83,6 +83,9 @@ RABBITMQ:
ENABLED: false ENABLED: false
URI: "amqp://guest:guest@localhost:5672" URI: "amqp://guest:guest@localhost:5672"
WEBSOCKET:
ENABLED: false
# Global Webhook Settings # Global Webhook Settings
# Each instance's Webhook URL and events will be requested at the time it is created # Each instance's Webhook URL and events will be requested at the time it is created
WEBHOOK: WEBHOOK:

View File

@ -1,7 +1,7 @@
import { Server } from 'http'; import { Server } from 'http';
import { Server as SocketIO } from 'socket.io'; import { Server as SocketIO } from 'socket.io';
import { configService, Cors } from '../config/env.config'; import { configService, Cors, Websocket } from '../config/env.config';
import { Logger } from '../config/logger.config'; import { Logger } from '../config/logger.config';
const logger = new Logger('Socket'); const logger = new Logger('Socket');
@ -11,22 +11,25 @@ let io: SocketIO;
const cors = configService.get<Cors>('CORS').ORIGIN; const cors = configService.get<Cors>('CORS').ORIGIN;
export const initIO = (httpServer: Server) => { export const initIO = (httpServer: Server) => {
io = new SocketIO(httpServer, { if (configService.get<Websocket>('WEBSOCKET').ENABLED) {
cors: { io = new SocketIO(httpServer, {
origin: cors, cors: {
}, origin: cors,
}); },
io.on('connection', (socket) => {
logger.info('User connected');
socket.on('disconnect', () => {
logger.info('User disconnected');
}); });
});
logger.info('Socket.io initialized'); io.on('connection', (socket) => {
return io; logger.info('User connected');
socket.on('disconnect', () => {
logger.info('User disconnected');
});
});
logger.info('Socket.io initialized');
return io;
}
return null;
}; };
export const getIO = (): SocketIO => { export const getIO = (): SocketIO => {

View File

@ -64,6 +64,7 @@ export class InstanceController {
typebot_url, typebot_url,
typebot, typebot,
typebot_expire, typebot_expire,
typebot_keyword_finish,
typebot_delay_message, typebot_delay_message,
typebot_unknown_message, typebot_unknown_message,
}: InstanceDto) { }: InstanceDto) {
@ -243,6 +244,7 @@ export class InstanceController {
url: typebot_url, url: typebot_url,
typebot: typebot, typebot: typebot,
expire: typebot_expire, expire: typebot_expire,
keyword_finish: typebot_keyword_finish,
delay_message: typebot_delay_message, delay_message: typebot_delay_message,
unknown_message: typebot_unknown_message, unknown_message: typebot_unknown_message,
}); });
@ -286,7 +288,7 @@ export class InstanceController {
webhook_by_events, webhook_by_events,
events: webhookEvents, events: webhookEvents,
}, },
websocker: { websocket: {
enabled: websocket_enabled, enabled: websocket_enabled,
events: websocketEvents, events: websocketEvents,
}, },
@ -299,6 +301,7 @@ export class InstanceController {
url: typebot_url, url: typebot_url,
typebot, typebot,
expire: typebot_expire, expire: typebot_expire,
keyword_finish: typebot_keyword_finish,
delay_message: typebot_delay_message, delay_message: typebot_delay_message,
unknown_message: typebot_unknown_message, unknown_message: typebot_unknown_message,
}, },
@ -377,7 +380,7 @@ export class InstanceController {
webhook_by_events, webhook_by_events,
events: webhookEvents, events: webhookEvents,
}, },
websocker: { websocket: {
enabled: websocket_enabled, enabled: websocket_enabled,
events: websocketEvents, events: websocketEvents,
}, },
@ -390,6 +393,7 @@ export class InstanceController {
url: typebot_url, url: typebot_url,
typebot, typebot,
expire: typebot_expire, expire: typebot_expire,
keyword_finish: typebot_keyword_finish,
delay_message: typebot_delay_message, delay_message: typebot_delay_message,
unknown_message: typebot_unknown_message, unknown_message: typebot_unknown_message,
}, },

View File

@ -25,6 +25,7 @@ export class InstanceDto {
typebot_url?: string; typebot_url?: string;
typebot?: string; typebot?: string;
typebot_expire?: number; typebot_expire?: number;
typebot_keyword_finish?: string;
typebot_delay_message?: number; typebot_delay_message?: number;
typebot_unknown_message?: string; typebot_unknown_message?: string;
proxy_enabled?: boolean; proxy_enabled?: boolean;

View File

@ -11,6 +11,7 @@ export class TypebotDto {
url: string; url: string;
typebot?: string; typebot?: string;
expire?: number; expire?: number;
keyword_finish?: string;
delay_message?: number; delay_message?: number;
unknown_message?: string; unknown_message?: string;
sessions?: Session[]; sessions?: Session[];

View File

@ -16,6 +16,7 @@ export class TypebotRaw {
url: string; url: string;
typebot?: string; typebot?: string;
expire?: number; expire?: number;
keyword_finish?: string;
delay_message?: number; delay_message?: number;
unknown_message?: string; unknown_message?: string;
sessions?: Session[]; sessions?: Session[];
@ -27,6 +28,7 @@ const typebotSchema = new Schema<TypebotRaw>({
url: { type: String, required: true }, url: { type: String, required: true },
typebot: { type: String, required: true }, typebot: { type: String, required: true },
expire: { type: Number, required: true }, expire: { type: Number, required: true },
keyword_finish: { type: String, required: true },
delay_message: { type: Number, required: true }, delay_message: { type: Number, required: true },
unknown_message: { type: String, required: true }, unknown_message: { type: String, required: true },
sessions: [ sessions: [

View File

@ -50,6 +50,9 @@ export class TypebotService {
url: findData.url, url: findData.url,
typebot: findData.typebot, typebot: findData.typebot,
expire: findData.expire, expire: findData.expire,
keyword_finish: findData.keyword_finish,
delay_message: findData.delay_message,
unknown_message: findData.unknown_message,
sessions: findData.sessions, sessions: findData.sessions,
}; };
@ -70,6 +73,9 @@ export class TypebotService {
url: findData.url, url: findData.url,
typebot: findData.typebot, typebot: findData.typebot,
expire: findData.expire, expire: findData.expire,
keyword_finish: findData.keyword_finish,
delay_message: findData.delay_message,
unknown_message: findData.unknown_message,
sessions: findData.sessions, sessions: findData.sessions,
}; };
@ -143,6 +149,9 @@ export class TypebotService {
url: data.url, url: data.url,
typebot: data.typebot, typebot: data.typebot,
expire: data.expire, expire: data.expire,
keyword_finish: data.keyword_finish,
delay_message: data.delay_message,
unknown_message: data.unknown_message,
sessions: data.sessions, sessions: data.sessions,
}; };
@ -285,6 +294,9 @@ export class TypebotService {
const typebot = (await this.find(instance)).typebot; const typebot = (await this.find(instance)).typebot;
const sessions = ((await this.find(instance)).sessions as Session[]) ?? []; const sessions = ((await this.find(instance)).sessions as Session[]) ?? [];
const expire = (await this.find(instance)).expire; const expire = (await this.find(instance)).expire;
const keyword_finish = (await this.find(instance)).keyword_finish;
const delay_message = (await this.find(instance)).delay_message;
const unknown_message = (await this.find(instance)).unknown_message;
const session = sessions.find((session) => session.remoteJid === remoteJid); const session = sessions.find((session) => session.remoteJid === remoteJid);
@ -302,6 +314,9 @@ export class TypebotService {
url: url, url: url,
typebot: typebot, typebot: typebot,
expire: expire, expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
sessions: sessions, sessions: sessions,
remoteJid: remoteJid, remoteJid: remoteJid,
pushName: msg.pushName, pushName: msg.pushName,
@ -322,6 +337,9 @@ export class TypebotService {
url: url, url: url,
typebot: typebot, typebot: typebot,
expire: expire, expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
sessions: sessions, sessions: sessions,
remoteJid: remoteJid, remoteJid: remoteJid,
pushName: msg.pushName, pushName: msg.pushName,
@ -343,6 +361,9 @@ export class TypebotService {
url: url, url: url,
typebot: typebot, typebot: typebot,
expire: expire, expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
sessions, sessions,
}; };
@ -351,21 +372,40 @@ export class TypebotService {
const content = this.getConversationMessage(msg.message); const content = this.getConversationMessage(msg.message);
if (!content) { if (!content) {
if (this.waMonitor.waInstances[instance.instanceName].localTypebot.unknown_message) { if (unknown_message) {
this.waMonitor.waInstances[instance.instanceName].textMessage({ this.waMonitor.waInstances[instance.instanceName].textMessage({
number: remoteJid.split('@')[0], number: remoteJid.split('@')[0],
options: { options: {
delay: this.waMonitor.waInstances[instance.instanceName].localTypebot.delay_message || 1000, delay: delay_message || 1000,
presence: 'composing', presence: 'composing',
}, },
textMessage: { textMessage: {
text: this.waMonitor.waInstances[instance.instanceName].localTypebot.unknown_message, text: unknown_message,
}, },
}); });
} }
return; return;
} }
if (content.toLowerCase() === keyword_finish.toLowerCase()) {
sessions.splice(sessions.indexOf(session), 1);
const typebotData = {
enabled: true,
url: url,
typebot: typebot,
expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
sessions,
};
this.create(instance, typebotData);
return;
}
const reqData = { const reqData = {
message: content, message: content,
sessionId: session.sessionId.split('-')[1], sessionId: session.sessionId.split('-')[1],

View File

@ -61,6 +61,7 @@ import {
QrCode, QrCode,
Redis, Redis,
Webhook, Webhook,
Websocket,
} from '../../config/env.config'; } from '../../config/env.config';
import { Logger } from '../../config/logger.config'; import { Logger } from '../../config/logger.config';
import { INSTANCE_DIR, ROOT_DIR } from '../../config/path.config'; import { INSTANCE_DIR, ROOT_DIR } from '../../config/path.config';
@ -505,6 +506,9 @@ export class WAStartupService {
this.localTypebot.expire = data?.expire; this.localTypebot.expire = data?.expire;
this.logger.verbose(`Typebot expire: ${this.localTypebot.expire}`); this.logger.verbose(`Typebot expire: ${this.localTypebot.expire}`);
this.localTypebot.keyword_finish = data?.keyword_finish;
this.logger.verbose(`Typebot keyword_finish: ${this.localTypebot.keyword_finish}`);
this.localTypebot.delay_message = data?.delay_message; this.localTypebot.delay_message = data?.delay_message;
this.logger.verbose(`Typebot delay_message: ${this.localTypebot.delay_message}`); this.logger.verbose(`Typebot delay_message: ${this.localTypebot.delay_message}`);
@ -521,8 +525,9 @@ export class WAStartupService {
await this.repository.typebot.create(data, this.instanceName); await this.repository.typebot.create(data, this.instanceName);
this.logger.verbose(`Typebot typebot: ${data.typebot}`); this.logger.verbose(`Typebot typebot: ${data.typebot}`);
this.logger.verbose(`Typebot expire: ${data.expire}`); this.logger.verbose(`Typebot expire: ${data.expire}`);
this.logger.verbose(`Typebot sessions: ${data.delay_message}`); this.logger.verbose(`Typebot keyword_finish: ${data.keyword_finish}`);
this.logger.verbose(`Typebot sessions: ${data.unknown_message}`); this.logger.verbose(`Typebot delay_message: ${data.delay_message}`);
this.logger.verbose(`Typebot unknown_message: ${data.unknown_message}`);
Object.assign(this.localTypebot, data); Object.assign(this.localTypebot, data);
this.logger.verbose('Typebot set'); this.logger.verbose('Typebot set');
} }
@ -618,7 +623,7 @@ export class WAStartupService {
} }
} }
if (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); this.logger.verbose('Sending data to websocket on channel: ' + this.instance.name);
if (Array.isArray(websocketLocal) && websocketLocal.includes(we)) { if (Array.isArray(websocketLocal) && websocketLocal.includes(we)) {
this.logger.verbose('Sending data to websocket on event: ' + event); this.logger.verbose('Sending data to websocket on event: ' + event);

View File

@ -91,6 +91,7 @@ export declare namespace wa {
url?: string; url?: string;
typebot?: string; typebot?: string;
expire?: number; expire?: number;
keyword_finish?: string;
delay_message?: number; delay_message?: number;
unknown_message?: string; unknown_message?: string;
sessions?: Session[]; sessions?: Session[];