waha / src /core /config /GlobalWebhookConfig.ts
NitinBot002's picture
Upload 384 files
4327358 verified
import { ConfigService } from '@nestjs/config';
import { WAHAEvents } from '@waha/structures/enums.dto';
import {
CustomHeader,
HmacConfiguration,
RetriesConfiguration,
WebhookConfig,
} from '@waha/structures/webhooks.config.dto';
import { plainToInstance } from 'class-transformer';
import { validateSync, ValidationError } from 'class-validator';
enum Env {
WHATSAPP_HOOK_URL = 'WHATSAPP_HOOK_URL',
WHATSAPP_HOOK_EVENTS = 'WHATSAPP_HOOK_EVENTS',
WHATSAPP_HOOK_RETRIES_POLICY = 'WHATSAPP_HOOK_RETRIES_POLICY',
WHATSAPP_HOOK_RETRIES_DELAY_SECONDS = 'WHATSAPP_HOOK_RETRIES_DELAY_SECONDS',
WHATSAPP_HOOK_RETRIES_ATTEMPTS = 'WHATSAPP_HOOK_RETRIES_ATTEMPTS',
WHATSAPP_HOOK_HMAC_KEY = 'WHATSAPP_HOOK_HMAC_KEY',
WHATSAPP_HOOK_CUSTOM_HEADERS = 'WHATSAPP_HOOK_CUSTOM_HEADERS',
}
export class GlobalWebhookConfigConfig {
protected _config: WebhookConfig | null = null;
constructor(private configService: ConfigService) {}
private getUrl(): string | undefined {
return this.configService.get(Env.WHATSAPP_HOOK_URL);
}
private getEvents(): WAHAEvents[] {
const value = this.configService.get(Env.WHATSAPP_HOOK_EVENTS, '');
return value ? value.split(',') : [];
}
private getHmac(): HmacConfiguration | null {
const key = this.configService.get(Env.WHATSAPP_HOOK_HMAC_KEY, '');
if (!key) {
return null;
}
return {
key: key,
};
}
private getRetries(): RetriesConfiguration | null {
const policy: any = this.configService.get(
Env.WHATSAPP_HOOK_RETRIES_POLICY,
null,
);
const delaySeconds: any = this.configService.get(
Env.WHATSAPP_HOOK_RETRIES_DELAY_SECONDS,
null,
);
const attempts: any = this.configService.get(
Env.WHATSAPP_HOOK_RETRIES_ATTEMPTS,
null,
);
if (!policy && !delaySeconds && !attempts) {
return null;
}
return {
policy: policy,
delaySeconds: delaySeconds,
attempts: attempts,
};
}
private getCustomHeaders(): CustomHeader[] {
// key:value;key2:value
const value = this.configService.get(Env.WHATSAPP_HOOK_CUSTOM_HEADERS, '');
if (!value) {
return [];
}
const headers = value.split(';');
return headers.map((header: string) => {
const parts = header.split(':');
if (parts.length !== 2) {
throw new Error(
`${Env.WHATSAPP_HOOK_CUSTOM_HEADERS} - Invalid custom header, no ':' found in '${header}'`,
);
}
return {
name: parts[0],
value: parts[1],
};
});
}
get config() {
if (!this._config) {
this._config = this.parseWebhookConfig();
}
return this._config;
}
validateConfig(): string | null {
const config = this.parseWebhookConfig();
if (!config) {
return null;
}
const errors = validateSync(config);
if (errors.length > 0) {
return this.formatErrors([], errors, []).join('\n');
}
return;
}
private getEnv(key: string): string | null {
const keys = {
url: Env.WHATSAPP_HOOK_URL,
events: Env.WHATSAPP_HOOK_EVENTS,
'retries.policy': Env.WHATSAPP_HOOK_RETRIES_POLICY,
'retries.delaySeconds': Env.WHATSAPP_HOOK_RETRIES_DELAY_SECONDS,
'retries.attempts': Env.WHATSAPP_HOOK_RETRIES_ATTEMPTS,
'hmac.key': Env.WHATSAPP_HOOK_HMAC_KEY,
};
return keys[key] || null;
}
private formatErrors(
lines: string[],
errors: ValidationError[],
path: string[],
) {
for (const err of errors) {
path = [...path, err.property];
for (const key in err.constraints) {
if (!err.constraints.hasOwnProperty(key)) {
continue;
}
const property = path.join('.');
const env = this.getEnv(property);
if (env) {
const value = this.configService.get(env, '');
const line = `- ${env} (${property}): '${value}' => '${err.value}' - ${err.constraints[key]}`;
lines.push(line);
} else {
const line = `- ${property}: '${err.value}' - ${err.constraints[key]}`;
lines.push(line);
}
}
if (err.children) {
this.formatErrors(lines, err.children, path);
}
}
return lines;
}
private parseWebhookConfig(): WebhookConfig | null {
const url = this.getUrl();
const events = this.getEvents();
if (!url || events.length === 0) {
return null;
}
const data: WebhookConfig = {
url: url,
events: events,
hmac: this.getHmac(),
retries: this.getRetries(),
customHeaders: this.getCustomHeaders(),
};
return plainToInstance(WebhookConfig, data, {
enableImplicitConversion: true,
});
}
}