UNPKG

bottender

Version:

A framework for building conversational user interfaces.

118 lines 4.44 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const crypto_1 = __importDefault(require("crypto")); const invariant_1 = __importDefault(require("invariant")); const shortid_1 = __importDefault(require("shortid")); const facebook_batch_1 = require("facebook-batch"); class FacebookBaseConnector { constructor(options) { this._origin = undefined; this._skipAppSecretProof = undefined; this._mapPageToAccessToken = null; this._verifyToken = null; this._batchConfig = null; this._batchQueue = null; const { appId, appSecret, mapPageToAccessToken, verifyToken } = options; if ('client' in options) { this._client = options.client; this._batchConfig = null; } else { const { ClientClass, accessToken, origin, skipAppSecretProof, batchConfig, } = options; invariant_1.default(accessToken || mapPageToAccessToken, 'Facebook access token is required. Please make sure you have filled it correctly in `bottender.config.js` or `.env` file.'); invariant_1.default(appSecret, 'Facebook app secret is required. Please make sure you have filled it correctly in `bottender.config.js` or `.env` file.'); const clientConfig = { accessToken: accessToken || '', appSecret, origin, skipAppSecretProof, }; this._client = new ClientClass(clientConfig); this._batchConfig = batchConfig || null; if (this._batchConfig) { this._batchQueue = new facebook_batch_1.FacebookBatchQueue(clientConfig, this._batchConfig); } this._origin = origin; this._skipAppSecretProof = skipAppSecretProof; } this._appId = appId; this._appSecret = appSecret; this._mapPageToAccessToken = mapPageToAccessToken || null; this._verifyToken = verifyToken || shortid_1.default.generate(); } get client() { return this._client; } get verifyToken() { return this._verifyToken; } verifySignature(rawBody, signature) { if (typeof signature !== 'string') return false; const sha1 = signature.split('sha1=')[1]; if (!sha1) return false; const bufferFromSignature = Buffer.from(sha1, 'hex'); const hashBufferFromBody = crypto_1.default .createHmac('sha1', this._appSecret) .update(rawBody, 'utf8') .digest(); if (bufferFromSignature.length !== hashBufferFromBody.length) { return false; } return crypto_1.default.timingSafeEqual(bufferFromSignature, hashBufferFromBody); } preprocess({ method, headers, query, rawBody, }) { if (method.toLowerCase() === 'get') { if (query['hub.mode'] === 'subscribe' && query['hub.verify_token'] === this.verifyToken) { return { shouldNext: false, response: { status: 200, body: query['hub.challenge'], }, }; } return { shouldNext: false, response: { status: 403, body: 'Forbidden', }, }; } if (method.toLowerCase() !== 'post') { return { shouldNext: true, }; } if (headers['x-hub-signature'] && this.verifySignature(rawBody, headers['x-hub-signature'])) { return { shouldNext: true, }; } const error = { message: 'Facebook Signature Validation Failed!', request: { rawBody, headers: { 'x-hub-signature': headers['x-hub-signature'], }, }, }; return { shouldNext: false, response: { status: 400, body: { error }, }, }; } } exports.default = FacebookBaseConnector; //# sourceMappingURL=FacebookBaseConnector.js.map