Skip to content

Commit 7c5d94c

Browse files
committed
feat: Added Typebot integration
1 parent a16b5f4 commit 7c5d94c

File tree

11 files changed

+140
-63
lines changed

11 files changed

+140
-63
lines changed

.DS_Store

0 Bytes
Binary file not shown.

src/validate/validate.schema.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,11 +983,24 @@ export const typebotSchema: JSONSchema7 = {
983983
url: { type: 'string' },
984984
typebot: { type: 'string' },
985985
expire: { type: 'integer' },
986+
delay_message: { type: 'integer' },
987+
unknown_message: { type: 'string' },
986988
},
987989
required: ['enabled', 'url', 'typebot', 'expire'],
988990
...isNotEmpty('enabled', 'url', 'typebot', 'expire'),
989991
};
990992

993+
export const typebotStatusSchema: JSONSchema7 = {
994+
$id: v4(),
995+
type: 'object',
996+
properties: {
997+
remoteJid: { type: 'string' },
998+
status: { type: 'string', enum: ['opened', 'closed', 'paused'] },
999+
},
1000+
required: ['remoteJid', 'status'],
1001+
...isNotEmpty('remoteJid', 'status'),
1002+
};
1003+
9911004
export const proxySchema: JSONSchema7 = {
9921005
$id: v4(),
9931006
type: 'object',

src/whatsapp/controllers/instance.controller.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ export class InstanceController {
6464
typebot_url,
6565
typebot,
6666
typebot_expire,
67+
typebot_delay_message,
68+
typebot_unknown_message,
6769
}: InstanceDto) {
6870
try {
6971
this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
@@ -241,6 +243,8 @@ export class InstanceController {
241243
url: typebot_url,
242244
typebot: typebot,
243245
expire: typebot_expire,
246+
delay_message: typebot_delay_message,
247+
unknown_message: typebot_unknown_message,
244248
});
245249
} catch (error) {
246250
this.logger.log(error);
@@ -295,6 +299,8 @@ export class InstanceController {
295299
url: typebot_url,
296300
typebot,
297301
expire: typebot_expire,
302+
delay_message: typebot_delay_message,
303+
unknown_message: typebot_unknown_message,
298304
},
299305
settings,
300306
qrcode: getQrcode,
@@ -384,6 +390,8 @@ export class InstanceController {
384390
url: typebot_url,
385391
typebot,
386392
expire: typebot_expire,
393+
delay_message: typebot_delay_message,
394+
unknown_message: typebot_unknown_message,
387395
},
388396
settings,
389397
chatwoot: {

src/whatsapp/controllers/typebot.controller.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,9 @@ export class TypebotController {
3333
logger.verbose('requested findTypebot from ' + instance.instanceName + ' instance');
3434
return this.typebotService.find(instance);
3535
}
36+
37+
public async changeStatus(instance: InstanceDto, data: any) {
38+
logger.verbose('requested changeStatus from ' + instance.instanceName + ' instance');
39+
return this.typebotService.changeStatus(instance, data);
40+
}
3641
}

src/whatsapp/dto/instance.dto.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export class InstanceDto {
2525
typebot_url?: string;
2626
typebot?: string;
2727
typebot_expire?: number;
28+
typebot_delay_message?: number;
29+
typebot_unknown_message?: string;
2830
proxy_enabled?: boolean;
2931
proxy_proxy?: string;
3032
}

src/whatsapp/dto/typebot.dto.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export class Session {
22
remoteJid?: string;
33
sessionId?: string;
4+
status?: string;
45
createdAt?: number;
56
updateAt?: number;
67
}
@@ -10,5 +11,7 @@ export class TypebotDto {
1011
url: string;
1112
typebot?: string;
1213
expire?: number;
14+
delay_message?: number;
15+
unknown_message?: string;
1316
sessions?: Session[];
1417
}

src/whatsapp/models/typebot.model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { dbserver } from '../../libs/db.connect';
55
class Session {
66
remoteJid?: string;
77
sessionId?: string;
8+
status?: string;
89
createdAt?: number;
910
updateAt?: number;
1011
}
@@ -15,6 +16,8 @@ export class TypebotRaw {
1516
url: string;
1617
typebot?: string;
1718
expire?: number;
19+
delay_message?: number;
20+
unknown_message?: string;
1821
sessions?: Session[];
1922
}
2023

@@ -24,10 +27,13 @@ const typebotSchema = new Schema<TypebotRaw>({
2427
url: { type: String, required: true },
2528
typebot: { type: String, required: true },
2629
expire: { type: Number, required: true },
30+
delay_message: { type: Number, required: true },
31+
unknown_message: { type: String, required: true },
2732
sessions: [
2833
{
2934
remoteJid: { type: String, required: true },
3035
sessionId: { type: String, required: true },
36+
status: { type: String, required: true },
3137
createdAt: { type: Number, required: true },
3238
updateAt: { type: Number, required: true },
3339
},

src/whatsapp/routers/typebot.router.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { RequestHandler, Router } from 'express';
22

33
import { Logger } from '../../config/logger.config';
4-
import { instanceNameSchema, typebotSchema } from '../../validate/validate.schema';
4+
import { instanceNameSchema, typebotSchema, typebotStatusSchema } from '../../validate/validate.schema';
55
import { RouterBroker } from '../abstract/abstract.router';
66
import { InstanceDto } from '../dto/instance.dto';
77
import { TypebotDto } from '../dto/typebot.dto';
@@ -44,6 +44,22 @@ export class TypebotRouter extends RouterBroker {
4444
execute: (instance) => typebotController.findTypebot(instance),
4545
});
4646

47+
res.status(HttpStatus.OK).json(response);
48+
})
49+
.post(this.routerPath('changeStatus'), ...guards, async (req, res) => {
50+
logger.verbose('request received in findTypebot');
51+
logger.verbose('request body: ');
52+
logger.verbose(req.body);
53+
54+
logger.verbose('request query: ');
55+
logger.verbose(req.query);
56+
const response = await this.dataValidate<InstanceDto>({
57+
request: req,
58+
schema: typebotStatusSchema,
59+
ClassRef: InstanceDto,
60+
execute: (instance, data) => typebotController.changeStatus(instance, data),
61+
});
62+
4763
res.status(HttpStatus.OK).json(response);
4864
});
4965
}

src/whatsapp/services/typebot.service.ts

Lines changed: 75 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,57 @@ export class TypebotService {
3333
}
3434
}
3535

36+
public async changeStatus(instance: InstanceDto, data: any) {
37+
const remoteJid = data.remoteJid;
38+
const status = data.status;
39+
40+
const findData = await this.find(instance);
41+
42+
const session = findData.sessions.find((session) => session.remoteJid === remoteJid);
43+
44+
if (session) {
45+
if (status === 'closed') {
46+
findData.sessions.splice(findData.sessions.indexOf(session), 1);
47+
48+
const typebotData = {
49+
enabled: true,
50+
url: findData.url,
51+
typebot: findData.typebot,
52+
expire: findData.expire,
53+
sessions: findData.sessions,
54+
};
55+
56+
this.create(instance, typebotData);
57+
58+
return { typebot: { ...instance, typebot: typebotData } };
59+
}
60+
61+
findData.sessions.map((session) => {
62+
if (session.remoteJid === remoteJid) {
63+
session.status = status;
64+
}
65+
});
66+
}
67+
68+
const typebotData = {
69+
enabled: true,
70+
url: findData.url,
71+
typebot: findData.typebot,
72+
expire: findData.expire,
73+
sessions: findData.sessions,
74+
};
75+
76+
this.create(instance, typebotData);
77+
78+
return { typebot: { ...instance, typebot: typebotData } };
79+
}
80+
3681
private getTypeMessage(msg: any) {
3782
this.logger.verbose('get type message');
3883

3984
const types = {
4085
conversation: msg.conversation,
41-
imageMessage: msg.imageMessage?.caption,
42-
videoMessage: msg.videoMessage?.caption,
4386
extendedTextMessage: msg.extendedTextMessage?.text,
44-
messageContextInfo: msg.messageContextInfo?.stanzaId,
45-
stickerMessage: undefined,
46-
documentMessage: msg.documentMessage?.caption,
47-
documentWithCaptionMessage: msg.documentWithCaptionMessage?.message?.documentMessage?.caption,
48-
audioMessage: msg.audioMessage?.caption,
49-
contactMessage: msg.contactMessage?.vcard,
50-
contactsArrayMessage: msg.contactsArrayMessage,
51-
locationMessage: msg.locationMessage,
52-
liveLocationMessage: msg.liveLocationMessage,
5387
};
5488

5589
this.logger.verbose('type message: ' + types);
@@ -86,6 +120,10 @@ export class TypebotService {
86120
sessionId: id,
87121
startParams: {
88122
typebot: data.typebot,
123+
prefilledVariables: {
124+
remoteJid: data.remoteJid,
125+
pushName: data.pushName,
126+
},
89127
},
90128
};
91129

@@ -95,6 +133,7 @@ export class TypebotService {
95133
data.sessions.push({
96134
remoteJid: data.remoteJid,
97135
sessionId: `${id}-${request.data.sessionId}`,
136+
status: 'opened',
98137
createdAt: Date.now(),
99138
updateAt: Date.now(),
100139
});
@@ -114,23 +153,9 @@ export class TypebotService {
114153
}
115154

116155
public async sendWAMessage(instance: InstanceDto, remoteJid: string, messages: any[], input: any[]) {
117-
processMessages(this.waMonitor.waInstances[instance.instanceName], messages, input)
118-
.then(async () => {
119-
if (!input) {
120-
const typebotData = await this.find(instance);
121-
122-
const session = typebotData.sessions.find((session) => session.remoteJid === remoteJid);
123-
124-
if (session) {
125-
typebotData.sessions.splice(typebotData.sessions.indexOf(session), 1);
126-
127-
this.create(instance, typebotData);
128-
}
129-
}
130-
})
131-
.catch((err) => {
132-
console.error('Erro ao processar mensagens:', err);
133-
});
156+
processMessages(this.waMonitor.waInstances[instance.instanceName], messages, input).catch((err) => {
157+
console.error('Erro ao processar mensagens:', err);
158+
});
134159

135160
async function processMessages(instance, messages, input) {
136161
for (const message of messages) {
@@ -174,7 +199,7 @@ export class TypebotService {
174199
await instance.textMessage({
175200
number: remoteJid.split('@')[0],
176201
options: {
177-
delay: 1200,
202+
delay: instance.localTypebot.delay_message || 1000,
178203
presence: 'composing',
179204
linkPreview: linkPreview,
180205
},
@@ -188,7 +213,7 @@ export class TypebotService {
188213
await instance.mediaMessage({
189214
number: remoteJid.split('@')[0],
190215
options: {
191-
delay: 1200,
216+
delay: instance.localTypebot.delay_message || 1000,
192217
presence: 'composing',
193218
},
194219
mediaMessage: {
@@ -202,7 +227,7 @@ export class TypebotService {
202227
await instance.mediaMessage({
203228
number: remoteJid.split('@')[0],
204229
options: {
205-
delay: 1200,
230+
delay: instance.localTypebot.delay_message || 1000,
206231
presence: 'composing',
207232
},
208233
mediaMessage: {
@@ -216,7 +241,7 @@ export class TypebotService {
216241
await instance.audioWhatsapp({
217242
number: remoteJid.split('@')[0],
218243
options: {
219-
delay: 1200,
244+
delay: instance.localTypebot.delay_message || 1000,
220245
presence: 'recording',
221246
encoding: true,
222247
},
@@ -279,6 +304,7 @@ export class TypebotService {
279304
expire: expire,
280305
sessions: sessions,
281306
remoteJid: remoteJid,
307+
pushName: msg.pushName,
282308
});
283309

284310
await this.sendWAMessage(instance, remoteJid, data.messages, data.input);
@@ -287,13 +313,18 @@ export class TypebotService {
287313
}
288314
}
289315

316+
if (session && session.status !== 'opened') {
317+
return;
318+
}
319+
290320
if (!session) {
291321
const data = await this.createNewSession(instance, {
292322
url: url,
293323
typebot: typebot,
294324
expire: expire,
295325
sessions: sessions,
296326
remoteJid: remoteJid,
327+
pushName: msg.pushName,
297328
});
298329

299330
await this.sendWAMessage(instance, remoteJid, data.messages, data.input);
@@ -320,22 +351,18 @@ export class TypebotService {
320351
const content = this.getConversationMessage(msg.message);
321352

322353
if (!content) {
323-
return;
324-
}
325-
326-
if (content.toLowerCase() === 'sair') {
327-
sessions.splice(sessions.indexOf(session), 1);
328-
329-
const typebotData = {
330-
enabled: true,
331-
url: url,
332-
typebot: typebot,
333-
expire: expire,
334-
sessions,
335-
};
336-
337-
this.create(instance, typebotData);
338-
354+
if (this.waMonitor.waInstances[instance.instanceName].localTypebot.unknown_message) {
355+
this.waMonitor.waInstances[instance.instanceName].textMessage({
356+
number: remoteJid.split('@')[0],
357+
options: {
358+
delay: this.waMonitor.waInstances[instance.instanceName].localTypebot.delay_message || 1000,
359+
presence: 'composing',
360+
},
361+
textMessage: {
362+
text: this.waMonitor.waInstances[instance.instanceName].localTypebot.unknown_message,
363+
},
364+
});
365+
}
339366
return;
340367
}
341368

@@ -346,18 +373,6 @@ export class TypebotService {
346373

347374
const request = await axios.post(url + '/api/v1/sendMessage', reqData);
348375

349-
if (!request.data.input) {
350-
sessions.splice(sessions.indexOf(session), 1);
351-
352-
await this.createNewSession(instance, {
353-
url: url,
354-
typebot: typebot,
355-
expire: expire,
356-
sessions: sessions,
357-
remoteJid: remoteJid,
358-
});
359-
}
360-
361376
await this.sendWAMessage(instance, remoteJid, request.data.messages, request.data.input);
362377

363378
return;

0 commit comments

Comments
 (0)