whatsapp-lib
Version:
This is a Node.JS library built to simplify using the Whatsapp Cloud API
139 lines (105 loc) • 4.62 kB
JavaScript
const axios = require('axios');
const express = require('express');
const { EventEmitter } = require('events');
class Whatsapp extends EventEmitter {
app = null;
handle_errors = false;
api = 'https://graph.facebook.com/'
AccessToken;
from_phone_number_id;
API_version;
whatsapp_headers;
constructor(AccessToken, from_phone_number_id, API_version = 16, handle_errors = false) {
super();
this.AccessToken = AccessToken;
this.from_phone_number_id = from_phone_number_id;
this.set_API_version(API_version);
this.whatsapp_headers = {
'Content-Type': 'application/json',
access_token: `${this.AccessToken}`
};
this.set_errorHandling(handle_errors);
}
listen(...args) {
if (this.app == null) {
this.app = express();
this.app.use(express.json());
}
return this.app.listen(...args);
}
open_webhook_verification(path, verify_token) {
this.app.get(path, (req, res) => {
if (
req.query['hub.mode'] == 'subscribe' &&
req.query['hub.verify_token'] == verify_token
) {
res.send(req.query['hub.challenge']);
} else {
res.sendStatus(400);
}
});
}
set_API_version(API_version) {
if (typeof API_version === 'string') {
const version_match = API_version.match(/(v)?(\d\d)(\.0)?(\/)?/);
if (version_match == null) throw new Error(`'API_version' is invalid.`)
this.API_version = `v${parseInt(version_match[2]).toFixed(1)}`;
} else if (typeof API_version === 'number') this.API_version = `v${API_version.toFixed(1)}`;
else throw new Error(`'version' must be of type 'number' or 'string', instead received '${typeof API_version}': ${API_version}`)
}
set_errorHandling(handle_errors) {
if (typeof handle_errors === 'boolean') {
this.handle_errors = handle_errors;
} else if (typeof handle_errors === 'string') {
if (handle_errors == 'true') this.handle_errors = true;
else if (handle_errors == 'false') this.handle_errors = false;
else throw new Error(`Boolean value 'handle_errors' must be either true or false, instead received a variable of type '${typeof handle_errors}': ${handle_errors}`);
} else throw new Error(`Boolean value 'handle_errors' must be either true or false, instead received a variable of type '${typeof handle_errors}': ${handle_errors}`);
}
sendMessage(phoneNumber_or_waID, textBody, messageID_reply = undefined) {
const URL = this.api + this.API_version + '/' + this.from_phone_number_id + '/messages' + '?access_token=' + this.AccessToken;
const payload = {
"messaging_product": "whatsapp",
"context": prepContext(messageID_reply),
"to": phoneNumber_or_waID,
"type": "text",
"text": {
"preview_url": false,
"body": textBody
}
}
return request('POST', URL, payload)
}
sendTemplate(phoneNumber_or_waID) {
const URL = this.api + this.API_version + '/' + this.from_phone_number_id + '/messages' + '?access_token=' + this.AccessToken;
const payload = {
"messaging_product": "whatsapp",
"to": phoneNumber_or_waID,
"type": "template",
"template": { "name": "hello_world", "language": { "code": "en_US" } }
}
return request('POST', URL, payload);
}
}
async function request(method, url, payload) {
method = method.toLowerCase();
try {
const response = await (method == 'get'
?
axios[method](url, { headers: this.whatsapp_headers })
:
axios[method](url, payload, { headers: this.whatsapp_headers })
);
return response.data;
} catch (err) {
return err.response.data;
}
}
function prepContext(messageID_reply) {
if (typeof messageID_reply === 'undefined') return undefined; // undefined so that the 'context' property is omitted when stringified
if (typeof messageID_reply === 'boolean') return undefined; // undefined so that the 'context' property is omitted when stringified
return {
"message_id": messageID_reply
}
}
module.exports = Whatsapp;