Skip to content

Commit f3cb8c5

Browse files
committed
feat: added proxy endpoint
1 parent 469e696 commit f3cb8c5

16 files changed

+327
-3
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,13 @@
6464
"js-yaml": "^4.1.0",
6565
"jsonschema": "^1.4.1",
6666
"jsonwebtoken": "^8.5.1",
67+
"libphonenumber-js": "^1.10.39",
6768
"link-preview-js": "^3.0.4",
6869
"mongoose": "^6.10.5",
6970
"node-cache": "^5.1.2",
7071
"node-mime-types": "^1.1.0",
7172
"pino": "^8.11.0",
72-
"proxy-agent": "^6.2.1",
73+
"proxy-agent": "^6.3.0",
7374
"qrcode": "^1.5.1",
7475
"qrcode-terminal": "^0.12.0",
7576
"redis": "^4.6.5",

src/validate/validate.schema.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,3 +987,14 @@ export const typebotSchema: JSONSchema7 = {
987987
required: ['enabled', 'url', 'typebot', 'expire'],
988988
...isNotEmpty('enabled', 'url', 'typebot', 'expire'),
989989
};
990+
991+
export const proxySchema: JSONSchema7 = {
992+
$id: v4(),
993+
type: 'object',
994+
properties: {
995+
enabled: { type: 'boolean', enum: [true, false] },
996+
proxy: { type: 'string' },
997+
},
998+
required: ['enabled', 'proxy'],
999+
...isNotEmpty('enabled', 'proxy'),
1000+
};

src/whatsapp/controllers/instance.controller.ts

Lines changed: 36 additions & 0 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 { RabbitmqService } from '../services/rabbitmq.service';
1515
import { SettingsService } from '../services/settings.service';
16+
import { TypebotService } from '../services/typebot.service';
1617
import { WebhookService } from '../services/webhook.service';
1718
import { WebsocketService } from '../services/websocket.service';
1819
import { WAStartupService } from '../services/whatsapp.service';
@@ -30,6 +31,7 @@ export class InstanceController {
3031
private readonly settingsService: SettingsService,
3132
private readonly websocketService: WebsocketService,
3233
private readonly rabbitmqService: RabbitmqService,
34+
private readonly typebotService: TypebotService,
3335
private readonly cache: RedisCache,
3436
) {}
3537

@@ -59,6 +61,9 @@ export class InstanceController {
5961
websocket_events,
6062
rabbitmq_enabled,
6163
rabbitmq_events,
64+
typebot_url,
65+
typebot,
66+
typebot_expire,
6267
}: InstanceDto) {
6368
try {
6469
this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
@@ -223,6 +228,25 @@ export class InstanceController {
223228
}
224229
}
225230

231+
if (typebot_url) {
232+
try {
233+
if (!isURL(typebot_url, { require_tld: false })) {
234+
throw new BadRequestException('Invalid "url" property in typebot_url');
235+
}
236+
237+
this.logger.verbose('creating typebot');
238+
239+
this.typebotService.create(instance, {
240+
enabled: true,
241+
url: typebot_url,
242+
typebot: typebot,
243+
expire: typebot_expire,
244+
});
245+
} catch (error) {
246+
this.logger.log(error);
247+
}
248+
}
249+
226250
this.logger.verbose('creating settings');
227251
const settings: wa.LocalSettings = {
228252
reject_call: reject_call || false,
@@ -266,6 +290,12 @@ export class InstanceController {
266290
enabled: rabbitmq_enabled,
267291
events: rabbitmqEvents,
268292
},
293+
typebot: {
294+
enabled: typebot_url ? true : false,
295+
url: typebot_url,
296+
typebot,
297+
expire: typebot_expire,
298+
},
269299
settings,
270300
qrcode: getQrcode,
271301
};
@@ -349,6 +379,12 @@ export class InstanceController {
349379
enabled: rabbitmq_enabled,
350380
events: rabbitmqEvents,
351381
},
382+
typebot: {
383+
enabled: typebot_url ? true : false,
384+
url: typebot_url,
385+
typebot,
386+
expire: typebot_expire,
387+
},
352388
settings,
353389
chatwoot: {
354390
enabled: true,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Logger } from '../../config/logger.config';
2+
import { InstanceDto } from '../dto/instance.dto';
3+
import { ProxyDto } from '../dto/proxy.dto';
4+
import { ProxyService } from '../services/proxy.service';
5+
6+
const logger = new Logger('ProxyController');
7+
8+
export class ProxyController {
9+
constructor(private readonly proxyService: ProxyService) {}
10+
11+
public async createProxy(instance: InstanceDto, data: ProxyDto) {
12+
logger.verbose('requested createProxy from ' + instance.instanceName + ' instance');
13+
14+
if (!data.enabled) {
15+
logger.verbose('proxy disabled');
16+
data.proxy = '';
17+
}
18+
19+
return this.proxyService.create(instance, data);
20+
}
21+
22+
public async findProxy(instance: InstanceDto) {
23+
logger.verbose('requested findProxy from ' + instance.instanceName + ' instance');
24+
return this.proxyService.find(instance);
25+
}
26+
}

src/whatsapp/dto/instance.dto.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@ export class InstanceDto {
2222
websocket_events?: string[];
2323
rabbitmq_enabled?: boolean;
2424
rabbitmq_events?: string[];
25+
typebot_url?: string;
26+
typebot?: string;
27+
typebot_expire?: number;
28+
proxy_enabled?: boolean;
29+
proxy_proxy?: string;
2530
}

src/whatsapp/dto/proxy.dto.ts

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

src/whatsapp/models/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export * from './chat.model';
33
export * from './chatwoot.model';
44
export * from './contact.model';
55
export * from './message.model';
6+
export * from './proxy.model';
67
export * from './rabbitmq.model';
78
export * from './settings.model';
89
export * from './typebot.model';

src/whatsapp/models/proxy.model.ts

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 ProxyRaw {
6+
_id?: string;
7+
enabled?: boolean;
8+
proxy?: string;
9+
}
10+
11+
const proxySchema = new Schema<ProxyRaw>({
12+
_id: { type: String, _id: true },
13+
enabled: { type: Boolean, required: true },
14+
proxy: { type: String, required: true },
15+
});
16+
17+
export const ProxyModel = dbserver?.model(ProxyRaw.name, proxySchema, 'proxy');
18+
export type IProxyModel = typeof ProxyModel;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { readFileSync } from 'fs';
2+
import { join } from 'path';
3+
4+
import { ConfigService } from '../../config/env.config';
5+
import { Logger } from '../../config/logger.config';
6+
import { IInsert, Repository } from '../abstract/abstract.repository';
7+
import { IProxyModel, ProxyRaw } from '../models';
8+
9+
export class ProxyRepository extends Repository {
10+
constructor(private readonly proxyModel: IProxyModel, private readonly configService: ConfigService) {
11+
super(configService);
12+
}
13+
14+
private readonly logger = new Logger('ProxyRepository');
15+
16+
public async create(data: ProxyRaw, instance: string): Promise<IInsert> {
17+
try {
18+
this.logger.verbose('creating proxy');
19+
if (this.dbSettings.ENABLED) {
20+
this.logger.verbose('saving proxy to db');
21+
const insert = await this.proxyModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
22+
23+
this.logger.verbose('proxy saved to db: ' + insert.modifiedCount + ' proxy');
24+
return { insertCount: insert.modifiedCount };
25+
}
26+
27+
this.logger.verbose('saving proxy to store');
28+
29+
this.writeStore<ProxyRaw>({
30+
path: join(this.storePath, 'proxy'),
31+
fileName: instance,
32+
data,
33+
});
34+
35+
this.logger.verbose('proxy saved to store in path: ' + join(this.storePath, 'proxy') + '/' + instance);
36+
37+
this.logger.verbose('proxy created');
38+
return { insertCount: 1 };
39+
} catch (error) {
40+
return error;
41+
}
42+
}
43+
44+
public async find(instance: string): Promise<ProxyRaw> {
45+
try {
46+
this.logger.verbose('finding proxy');
47+
if (this.dbSettings.ENABLED) {
48+
this.logger.verbose('finding proxy in db');
49+
return await this.proxyModel.findOne({ _id: instance });
50+
}
51+
52+
this.logger.verbose('finding proxy in store');
53+
return JSON.parse(
54+
readFileSync(join(this.storePath, 'proxy', instance + '.json'), {
55+
encoding: 'utf-8',
56+
}),
57+
) as ProxyRaw;
58+
} catch (error) {
59+
return {};
60+
}
61+
}
62+
}

src/whatsapp/repository/repository.manager.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ChatwootRepository } from './chatwoot.repository';
1010
import { ContactRepository } from './contact.repository';
1111
import { MessageRepository } from './message.repository';
1212
import { MessageUpRepository } from './messageUp.repository';
13+
import { ProxyRepository } from './proxy.repository';
1314
import { RabbitmqRepository } from './rabbitmq.repository';
1415
import { SettingsRepository } from './settings.repository';
1516
import { TypebotRepository } from './typebot.repository';
@@ -27,6 +28,7 @@ export class RepositoryBroker {
2728
public readonly websocket: WebsocketRepository,
2829
public readonly rabbitmq: RabbitmqRepository,
2930
public readonly typebot: TypebotRepository,
31+
public readonly proxy: ProxyRepository,
3032
public readonly auth: AuthRepository,
3133
private configService: ConfigService,
3234
dbServer?: MongoClient,
@@ -60,6 +62,7 @@ export class RepositoryBroker {
6062
const websocketDir = join(storePath, 'websocket');
6163
const rabbitmqDir = join(storePath, 'rabbitmq');
6264
const typebotDir = join(storePath, 'typebot');
65+
const proxyDir = join(storePath, 'proxy');
6366
const tempDir = join(storePath, 'temp');
6467

6568
if (!fs.existsSync(authDir)) {
@@ -106,6 +109,10 @@ export class RepositoryBroker {
106109
this.logger.verbose('creating typebot dir: ' + typebotDir);
107110
fs.mkdirSync(typebotDir, { recursive: true });
108111
}
112+
if (!fs.existsSync(proxyDir)) {
113+
this.logger.verbose('creating proxy dir: ' + proxyDir);
114+
fs.mkdirSync(proxyDir, { recursive: true });
115+
}
109116
if (!fs.existsSync(tempDir)) {
110117
this.logger.verbose('creating temp dir: ' + tempDir);
111118
fs.mkdirSync(tempDir, { recursive: true });

0 commit comments

Comments
 (0)