@brighthustle/adonisjs-whatsapp
Version:
Connect your WhatsApp Cloud API with AdonisJS
397 lines (396 loc) • 15.7 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = __importDefault(require("axios"));
const Helpers_1 = __importDefault(require("./Helpers"));
const enum_1 = require("./types/enum");
class WhatsAppClient {
constructor(config, db) {
this.config = config;
this.db = db;
this.headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.config.config?.accessToken,
};
this.mandatory = {
messaging_product: 'whatsapp',
recipient_type: 'individual',
};
}
async send(data, parse = true) {
let { timeout, phoneNumberId, graphUrl, graphVersion } = this.config.config;
let headers = this.headers;
let apiProvider = null;
let url = `${graphUrl}/${graphVersion}/${phoneNumberId}/messages`;
if (!this.config.db) {
this.validateApiProvider(this.config.config.apiProvider);
apiProvider = this.config.config.apiProvider;
headers = this.getHeaders(apiProvider, this.config.config.accessToken);
}
if (this.config.db) {
if (!data.from) {
throw new Error('From (id for whatsapp db) is required as db config is enabled.');
}
if (!this.connection) {
this.db.connection(this.config.db.connectionName);
}
const waResponse = await this.db
.query()
.select('*')
.from(this.config.db.tableName)
.where('id', data.from)
.first();
if (waResponse) {
phoneNumberId = waResponse.phone_number_id;
apiProvider = waResponse.api_provider;
graphVersion = waResponse.graph_version ?? graphVersion;
graphUrl = waResponse.graph_url ?? graphUrl;
headers = this.getHeaders(apiProvider, waResponse.access_token);
}
else {
throw new Error('Incorrect Phone Number ID');
}
}
if (apiProvider === enum_1.ApiProvider.MAG91_API) {
if (data.type === 'text') {
url = `${graphUrl}/${graphVersion}/whatsapp/whatsapp-outbound-message/?integrated_number=${phoneNumberId}&recipient_number=${data.to}&content_type=text&text=${data.text.body}`;
}
else if (data.type === 'template') {
data = Helpers_1.default.transformToMsg91SendTemplate(phoneNumberId, data.template.name, data.template.language.code, data.template.components, data.to);
url = `${graphUrl}/${graphVersion}/whatsapp/whatsapp-outbound-message/bulk/`;
}
else {
throw new Error('Not implemented in msg 91 apis');
}
}
else {
url = `${graphUrl}/${graphVersion}/${phoneNumberId}/messages`;
data = { ...this.mandatory, ...data };
}
const response = await (0, axios_1.default)({
validateStatus: (status) => status <= 999,
method: 'POST',
url: url,
timeout,
headers: headers,
data: data,
responseType: 'json',
});
if ('error' in response.data) {
throw new Error(response.data.error?.error_data?.details || response.data.error?.message);
}
return parse
? apiProvider === enum_1.ApiProvider.CLOUD_API
? this.parse(response.data)
: this.parseMsg91(response.data, data.from)
: response.data;
}
async media(media, from) {
let { timeout, graphUrl, graphVersion } = this.config.config;
let dbHeaders = null;
if (this.config.db) {
if (!from) {
throw new Error('From (id for whatsapp db) is required as db config is enabled.');
}
if (!this.connection) {
this.db.connection(this.config.db.connectionName);
}
const waResponse = await this.db
.query()
.select('*')
.from(this.config.db.tableName)
.where('id', from)
.first();
if (waResponse) {
graphVersion = waResponse.graph_version ?? graphVersion;
dbHeaders = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + waResponse.access_token,
};
}
else {
throw new Error('Incorrect Phone Number ID');
}
}
const response = await (0, axios_1.default)({
validateStatus: (status) => status <= 999,
method: 'GET',
url: `${graphUrl}/${graphVersion}/${media}`,
timeout,
headers: dbHeaders ?? this.headers,
responseType: 'json',
});
if ('error' in response.data) {
throw new Error(response.data.error?.error_data?.details || response.data.error?.message);
}
return response.data;
}
async upload(form, from) {
let { timeout, phoneNumberId, graphUrl, graphVersion } = this.config.config;
let dbHeaders = null;
if (this.config.db) {
if (!from) {
throw new Error('From (id for whatsapp db) is required as db config is enabled.');
}
if (!this.connection) {
this.db.connection(this.config.db.connectionName);
}
const waResponse = await this.db
.query()
.select('*')
.from(this.config.db.tableName)
.where('id', from)
.first();
if (waResponse) {
graphVersion = waResponse.graph_version ?? graphVersion;
phoneNumberId = waResponse.phone_number_id;
dbHeaders = {
...form.getHeaders(),
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + waResponse.access_token,
};
}
else {
throw new Error('Incorrect Phone Number ID');
}
}
const response = await (0, axios_1.default)({
validateStatus: (status) => status <= 999,
method: 'POST',
url: `${graphUrl}/${graphVersion}/${phoneNumberId}/media`,
timeout,
headers: dbHeaders ?? { ...form.getHeaders(), ...this.headers },
data: form,
responseType: 'json',
});
if ('error' in response.data) {
throw new Error(response.data.error?.error_data?.details || response.data.error?.message);
}
return response.data;
}
async createTemplate(data) {
let { timeout, whatsappBusinessId, graphUrl, graphVersion } = this.config.config;
let headers = this.headers;
let apiProvider = 'cloud-api';
if (!this.config.db) {
this.validateApiProvider(this.config.config.apiProvider);
apiProvider = this.config.config.apiProvider;
}
if (this.config.db) {
if (!data.from) {
throw new Error('From (id for whatsapp db) is required as db config is enabled.');
}
if (!this.connection) {
this.db.connection(this.config.db.connectionName);
}
const waResponse = await this.db
.query()
.select('*')
.from(this.config.db.tableName)
.where('id', data.from)
.first();
if (waResponse) {
graphVersion = waResponse.graph_version ?? graphVersion;
apiProvider = waResponse.api_provider;
whatsappBusinessId = waResponse.whatsapp_business_id;
if (apiProvider === enum_1.ApiProvider.CLOUD_API) {
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + waResponse.access_token,
};
}
if (apiProvider === enum_1.ApiProvider.MAG91_API) {
headers = {
'Content-Type': 'application/json',
'authkey': waResponse.access_token,
};
}
}
else {
throw new Error('Incorrect Phone Number ID');
}
}
const response = await (0, axios_1.default)({
validateStatus: (status) => status <= 999,
method: 'POST',
url: `${graphUrl}/${graphVersion}/${whatsappBusinessId}/message_templates`,
timeout,
headers: headers,
data: data,
responseType: 'json',
});
if ('error' in response.data) {
throw new Error(response.data.error?.error_data?.details || response.data.error?.message);
}
return response.data;
}
async getTemplates(options, from) {
let { timeout, whatsappBusinessId, graphUrl, graphVersion } = this.config.config;
let dbHeaders = null;
if (this.config.db) {
if (!from) {
throw new Error('From (id for whatsapp db) is required as db config is enabled.');
}
if (!this.connection) {
this.db.connection(this.config.db.connectionName);
}
const waResponse = await this.db
.query()
.select('*')
.from(this.config.db.tableName)
.where('id', from)
.first();
if (waResponse) {
graphVersion = waResponse.graph_version ?? graphVersion;
whatsappBusinessId = waResponse.whatsapp_business_id;
dbHeaders = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + waResponse.access_token,
};
}
else {
throw new Error('Incorrect Phone Number ID');
}
}
let qs = '';
if (options) {
if (options.fields && options.fields.length > 0) {
qs += qs.length > 0 ? '&' : '?';
qs += `fields=${options.fields.join(',')}`;
}
if (options.limit) {
qs += qs.length > 0 ? '&' : '?';
qs += `limit=${options.limit}`;
}
}
const response = await (0, axios_1.default)({
validateStatus: (status) => status <= 999,
method: 'GET',
url: `${graphUrl}/${graphVersion}/${whatsappBusinessId}/message_templates${qs}`,
timeout,
headers: dbHeaders ?? this.headers,
responseType: 'json',
});
if ('error' in response.data) {
throw new Error(response.data.error?.error_data?.details || response.data.error?.message);
}
return response.data;
}
async deleteTemplate(name, from) {
let { timeout, graphUrl, graphVersion, whatsappBusinessId } = this.config.config;
let dbHeaders = null;
if (this.config.db) {
if (!from) {
throw new Error('From (id for whatsapp db) is required as db config is enabled.');
}
if (!this.connection) {
this.db.connection(this.config.db.connectionName);
}
const waResponse = await this.db
.query()
.select('*')
.from(this.config.db.tableName)
.where('id', from)
.first();
if (waResponse) {
graphVersion = waResponse.graph_version ?? graphVersion;
whatsappBusinessId = waResponse.whatsapp_business_id;
dbHeaders = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + waResponse.access_token,
};
}
else {
throw new Error('Incorrect Phone Number ID');
}
}
const response = await (0, axios_1.default)({
validateStatus: (status) => status <= 999,
method: 'DELETE',
url: `${graphUrl}/${graphVersion}/${whatsappBusinessId}/message_templates?name=${name}`,
timeout,
headers: dbHeaders ?? this.headers,
responseType: 'json',
});
if ('error' in response.data) {
throw new Error(response.data.error?.error_data?.details || response.data.error?.message);
}
return response.data;
}
async download(url, from) {
let dbHeaders = null;
if (this.config.db) {
if (!from) {
throw new Error('From (id for whatsapp db) is required as db config is enabled.');
}
if (!this.connection) {
this.db.connection(this.config.db.connectionName);
}
const waResponse = await this.db
.query()
.select('*')
.from(this.config.db.tableName)
.where('id', from)
.first();
if (waResponse) {
dbHeaders = {
Authorization: 'Bearer ' + waResponse.access_token,
};
}
else {
throw new Error('Incorrect Phone Number ID');
}
}
const response = await (0, axios_1.default)({
validateStatus: (status) => status <= 999,
method: 'GET',
url: url,
headers: dbHeaders ?? { Authorization: 'Bearer ' + this.config.config.accessToken },
responseType: 'arraybuffer',
});
if ('error' in response.data) {
throw new Error(response.data.error?.error_data?.details || response.data.error?.message);
}
return response.data;
}
parse(data) {
return {
input: Number(data.contacts[0].input),
phone: data.contacts[0].wa_id,
wamid: data.messages[0].id,
};
}
parseMsg91(data, from) {
return {
input: 0,
phone: from,
wamid: data.request_id,
};
}
/**
* Validates if the provided apiProvider is one of the allowed values.
* @param apiProvider - The apiProvider to validate.
* @throws {Error} - Throws an error if apiProvider is not valid.
*/
validateApiProvider(apiProvider) {
if (!apiProvider) {
throw new Error('API provider is required: cloud-api | msg91.');
}
if (!Object.values(enum_1.ApiProvider).includes(apiProvider)) {
throw new Error(`Invalid API provider. Expected one of: ${Object.values(enum_1.ApiProvider).join(', ')}.`);
}
}
getHeaders(apiProvider, accessToken) {
const headers = { 'Content-Type': 'application/json' };
if (apiProvider === enum_1.ApiProvider.CLOUD_API) {
headers['Authorization'] = 'Bearer ' + accessToken;
}
else if (apiProvider === enum_1.ApiProvider.MAG91_API) {
headers['authkey'] = accessToken;
}
return headers;
}
}
exports.default = WhatsAppClient;