Skip to content

Commit 24c8803

Browse files
committed
feat: Added websocket with lib socket.io
1 parent b3b4ee7 commit 24c8803

16 files changed

Lines changed: 416 additions & 25 deletions

src/validate/validate.schema.ts

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -824,13 +824,11 @@ export const updateGroupDescriptionSchema: JSONSchema7 = {
824824
...isNotEmpty('groupJid', 'description'),
825825
};
826826

827-
// Webhook Schema
828827
export const webhookSchema: JSONSchema7 = {
829828
$id: v4(),
830829
type: 'object',
831830
properties: {
832831
url: { type: 'string' },
833-
enabled: { type: 'boolean', enum: [true, false] },
834832
events: {
835833
type: 'array',
836834
minItems: 0,
@@ -862,7 +860,7 @@ export const webhookSchema: JSONSchema7 = {
862860
},
863861
},
864862
},
865-
required: ['url', 'enabled'],
863+
required: ['url'],
866864
...isNotEmpty('url'),
867865
};
868866

@@ -896,3 +894,43 @@ export const settingsSchema: JSONSchema7 = {
896894
required: ['reject_call', 'groups_ignore', 'always_online', 'read_messages', 'read_status'],
897895
...isNotEmpty('reject_call', 'groups_ignore', 'always_online', 'read_messages', 'read_status'),
898896
};
897+
898+
export const websocketSchema: JSONSchema7 = {
899+
$id: v4(),
900+
type: 'object',
901+
properties: {
902+
enabled: { type: 'boolean', enum: [true, false] },
903+
events: {
904+
type: 'array',
905+
minItems: 0,
906+
items: {
907+
type: 'string',
908+
enum: [
909+
'APPLICATION_STARTUP',
910+
'QRCODE_UPDATED',
911+
'MESSAGES_SET',
912+
'MESSAGES_UPSERT',
913+
'MESSAGES_UPDATE',
914+
'MESSAGES_DELETE',
915+
'SEND_MESSAGE',
916+
'CONTACTS_SET',
917+
'CONTACTS_UPSERT',
918+
'CONTACTS_UPDATE',
919+
'PRESENCE_UPDATE',
920+
'CHATS_SET',
921+
'CHATS_UPSERT',
922+
'CHATS_UPDATE',
923+
'CHATS_DELETE',
924+
'GROUPS_UPSERT',
925+
'GROUP_UPDATE',
926+
'GROUP_PARTICIPANTS_UPDATE',
927+
'CONNECTION_UPDATE',
928+
'CALL',
929+
'NEW_JWT_TOKEN',
930+
],
931+
},
932+
},
933+
},
934+
required: ['enabled'],
935+
...isNotEmpty('enabled'),
936+
};

src/whatsapp/controllers/instance.controller.ts

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { ChatwootService } from '../services/chatwoot.service';
1313
import { WAMonitoringService } from '../services/monitor.service';
1414
import { SettingsService } from '../services/settings.service';
1515
import { WebhookService } from '../services/webhook.service';
16+
import { WebsocketService } from '../services/websocket.service';
1617
import { WAStartupService } from '../services/whatsapp.service';
1718
import { wa } from '../types/wa.types';
1819

@@ -26,6 +27,7 @@ export class InstanceController {
2627
private readonly webhookService: WebhookService,
2728
private readonly chatwootService: ChatwootService,
2829
private readonly settingsService: SettingsService,
30+
private readonly websocketService: WebsocketService,
2931
private readonly cache: RedisCache,
3032
) {}
3133

@@ -51,6 +53,8 @@ export class InstanceController {
5153
always_online,
5254
read_messages,
5355
read_status,
56+
websocket_enabled,
57+
websocket_events,
5458
}: InstanceDto) {
5559
try {
5660
this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
@@ -77,7 +81,7 @@ export class InstanceController {
7781

7882
this.logger.verbose('hash: ' + hash + ' generated');
7983

80-
let getEvents: string[];
84+
let webhookEvents: string[];
8185

8286
if (webhook) {
8387
if (!isURL(webhook, { require_tld: false })) {
@@ -121,7 +125,51 @@ export class InstanceController {
121125
webhook_by_events,
122126
});
123127

124-
getEvents = (await this.webhookService.find(instance)).events;
128+
webhookEvents = (await this.webhookService.find(instance)).events;
129+
} catch (error) {
130+
this.logger.log(error);
131+
}
132+
}
133+
134+
let websocketEvents: string[];
135+
136+
if (websocket_enabled) {
137+
this.logger.verbose('creating websocket');
138+
try {
139+
let newEvents: string[] = [];
140+
if (websocket_events.length === 0) {
141+
newEvents = [
142+
'APPLICATION_STARTUP',
143+
'QRCODE_UPDATED',
144+
'MESSAGES_SET',
145+
'MESSAGES_UPSERT',
146+
'MESSAGES_UPDATE',
147+
'MESSAGES_DELETE',
148+
'SEND_MESSAGE',
149+
'CONTACTS_SET',
150+
'CONTACTS_UPSERT',
151+
'CONTACTS_UPDATE',
152+
'PRESENCE_UPDATE',
153+
'CHATS_SET',
154+
'CHATS_UPSERT',
155+
'CHATS_UPDATE',
156+
'CHATS_DELETE',
157+
'GROUPS_UPSERT',
158+
'GROUP_UPDATE',
159+
'GROUP_PARTICIPANTS_UPDATE',
160+
'CONNECTION_UPDATE',
161+
'CALL',
162+
'NEW_JWT_TOKEN',
163+
];
164+
} else {
165+
newEvents = events;
166+
}
167+
this.websocketService.create(instance, {
168+
enabled: true,
169+
events: newEvents,
170+
});
171+
172+
websocketEvents = (await this.websocketService.find(instance)).events;
125173
} catch (error) {
126174
this.logger.log(error);
127175
}
@@ -157,9 +205,15 @@ export class InstanceController {
157205
status: 'created',
158206
},
159207
hash,
160-
webhook,
161-
webhook_by_events,
162-
events: getEvents,
208+
webhook: {
209+
webhook,
210+
webhook_by_events,
211+
events: webhookEvents,
212+
},
213+
websocker: {
214+
enabled: websocket_enabled,
215+
events: websocketEvents,
216+
},
163217
settings,
164218
qrcode: getQrcode,
165219
};
@@ -230,9 +284,15 @@ export class InstanceController {
230284
status: 'created',
231285
},
232286
hash,
233-
webhook,
234-
webhook_by_events,
235-
events: getEvents,
287+
webhook: {
288+
webhook,
289+
webhook_by_events,
290+
events: webhookEvents,
291+
},
292+
websocker: {
293+
enabled: websocket_enabled,
294+
events: websocketEvents,
295+
},
236296
settings,
237297
chatwoot: {
238298
enabled: true,

src/whatsapp/controllers/webhook.controller.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ export class WebhookController {
1414
public async createWebhook(instance: InstanceDto, data: WebhookDto) {
1515
logger.verbose('requested createWebhook from ' + instance.instanceName + ' instance');
1616

17-
if (data.enabled && !isURL(data.url, { require_tld: false })) {
17+
if (!isURL(data.url, { require_tld: false })) {
1818
throw new BadRequestException('Invalid "url" property');
1919
}
2020

21+
data.enabled = data.enabled ?? true;
22+
2123
if (!data.enabled) {
2224
logger.verbose('webhook disabled');
2325
data.url = '';
2426
data.events = [];
25-
}
26-
27-
if (data.events.length === 0) {
27+
} else if (data.events.length === 0) {
2828
logger.verbose('webhook events empty');
2929
data.events = [
3030
'APPLICATION_STARTUP',
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Logger } from '../../config/logger.config';
2+
import { InstanceDto } from '../dto/instance.dto';
3+
import { WebsocketDto } from '../dto/websocket.dto';
4+
import { WebsocketService } from '../services/websocket.service';
5+
6+
const logger = new Logger('WebsocketController');
7+
8+
export class WebsocketController {
9+
constructor(private readonly websocketService: WebsocketService) {}
10+
11+
public async createWebsocket(instance: InstanceDto, data: WebsocketDto) {
12+
logger.verbose('requested createWebsocket from ' + instance.instanceName + ' instance');
13+
14+
if (!data.enabled) {
15+
logger.verbose('websocket disabled');
16+
data.events = [];
17+
}
18+
19+
if (data.events.length === 0) {
20+
logger.verbose('websocket events empty');
21+
data.events = [
22+
'APPLICATION_STARTUP',
23+
'QRCODE_UPDATED',
24+
'MESSAGES_SET',
25+
'MESSAGES_UPSERT',
26+
'MESSAGES_UPDATE',
27+
'MESSAGES_DELETE',
28+
'SEND_MESSAGE',
29+
'CONTACTS_SET',
30+
'CONTACTS_UPSERT',
31+
'CONTACTS_UPDATE',
32+
'PRESENCE_UPDATE',
33+
'CHATS_SET',
34+
'CHATS_UPSERT',
35+
'CHATS_UPDATE',
36+
'CHATS_DELETE',
37+
'GROUPS_UPSERT',
38+
'GROUP_UPDATE',
39+
'GROUP_PARTICIPANTS_UPDATE',
40+
'CONNECTION_UPDATE',
41+
'CALL',
42+
'NEW_JWT_TOKEN',
43+
];
44+
}
45+
46+
return this.websocketService.create(instance, data);
47+
}
48+
49+
public async findWebsocket(instance: InstanceDto) {
50+
logger.verbose('requested findWebsocket from ' + instance.instanceName + ' instance');
51+
return this.websocketService.find(instance);
52+
}
53+
}

src/whatsapp/dto/instance.dto.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@ export class InstanceDto {
1818
chatwoot_sign_msg?: boolean;
1919
chatwoot_reopen_conversation?: boolean;
2020
chatwoot_conversation_pending?: boolean;
21+
websocket_enabled?: boolean;
22+
websocket_events?: string[];
2123
}

src/whatsapp/dto/websocket.dto.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export class WebsocketDto {
2+
enabled: boolean;
3+
events?: string[];
4+
}

src/whatsapp/models/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export * from './contact.model';
55
export * from './message.model';
66
export * from './settings.model';
77
export * from './webhook.model';
8+
export * from './websocket.model';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Schema } from 'mongoose';
2+
3+
import { dbserver } from '../../libs/db.connect';
4+
5+
export class WebsocketRaw {
6+
_id?: string;
7+
enabled?: boolean;
8+
events?: string[];
9+
}
10+
11+
const websocketSchema = new Schema<WebsocketRaw>({
12+
_id: { type: String, _id: true },
13+
enabled: { type: Boolean, required: true },
14+
events: { type: [String], required: true },
15+
});
16+
17+
export const WebsocketModel = dbserver?.model(WebsocketRaw.name, websocketSchema, 'websocket');
18+
export type IWebsocketModel = typeof WebsocketModel;

src/whatsapp/repository/repository.manager.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { MessageRepository } from './message.repository';
1212
import { MessageUpRepository } from './messageUp.repository';
1313
import { SettingsRepository } from './settings.repository';
1414
import { WebhookRepository } from './webhook.repository';
15+
import { WebsocketRepository } from './websocket.repository';
1516
export class RepositoryBroker {
1617
constructor(
1718
public readonly message: MessageRepository,
@@ -21,6 +22,7 @@ export class RepositoryBroker {
2122
public readonly webhook: WebhookRepository,
2223
public readonly chatwoot: ChatwootRepository,
2324
public readonly settings: SettingsRepository,
25+
public readonly websocket: WebsocketRepository,
2426
public readonly auth: AuthRepository,
2527
private configService: ConfigService,
2628
dbServer?: MongoClient,
@@ -51,6 +53,7 @@ export class RepositoryBroker {
5153
const webhookDir = join(storePath, 'webhook');
5254
const chatwootDir = join(storePath, 'chatwoot');
5355
const settingsDir = join(storePath, 'settings');
56+
const websocketDir = join(storePath, 'websocket');
5457
const tempDir = join(storePath, 'temp');
5558

5659
if (!fs.existsSync(authDir)) {
@@ -85,6 +88,10 @@ export class RepositoryBroker {
8588
this.logger.verbose('creating settings dir: ' + settingsDir);
8689
fs.mkdirSync(settingsDir, { recursive: true });
8790
}
91+
if (!fs.existsSync(websocketDir)) {
92+
this.logger.verbose('creating websocket dir: ' + websocketDir);
93+
fs.mkdirSync(websocketDir, { recursive: true });
94+
}
8895
if (!fs.existsSync(tempDir)) {
8996
this.logger.verbose('creating temp dir: ' + tempDir);
9097
fs.mkdirSync(tempDir, { recursive: true });

0 commit comments

Comments
 (0)