2016-03-17 02:44:34 +03:00
|
|
|
const debug = require('debug')('node-telegram-bot-api');
|
|
|
|
const https = require('https');
|
|
|
|
const http = require('http');
|
|
|
|
const fs = require('fs');
|
|
|
|
const bl = require('bl');
|
2017-01-02 13:58:46 +03:00
|
|
|
const Promise = require('bluebird');
|
2015-09-27 11:18:25 +02:00
|
|
|
|
2015-07-13 00:24:49 +02:00
|
|
|
|
2017-01-02 13:04:44 +03:00
|
|
|
class TelegramBotWebHook {
|
|
|
|
/**
|
|
|
|
* Sets up a webhook to receive updates
|
|
|
|
*
|
|
|
|
* @param {String} token Telegram API token
|
|
|
|
* @param {Boolean|Object} options WebHook options
|
|
|
|
* @param {Number} [options.port=8443] Port to bind to
|
|
|
|
* @param {Function} callback Function for process a new update
|
|
|
|
*/
|
2016-03-17 02:44:34 +03:00
|
|
|
constructor(token, options, callback) {
|
|
|
|
// define opts
|
|
|
|
if (typeof options === 'boolean') {
|
|
|
|
options = {}; // eslint-disable-line no-param-reassign
|
|
|
|
}
|
2017-01-02 13:04:44 +03:00
|
|
|
|
|
|
|
this.token = token;
|
|
|
|
this.options = options;
|
|
|
|
this.options.port = options.port || 8443;
|
2017-01-07 17:58:01 +03:00
|
|
|
this.options.https = options.https || {};
|
2017-01-02 13:04:44 +03:00
|
|
|
this.callback = callback;
|
|
|
|
this._regex = new RegExp(this.token);
|
|
|
|
this._webServer = null;
|
2017-01-06 22:26:25 +03:00
|
|
|
this._requestListener = this._requestListener.bind(this);
|
|
|
|
this._parseBody = this._parseBody.bind(this);
|
2016-03-17 02:44:34 +03:00
|
|
|
|
2017-01-07 17:58:01 +03:00
|
|
|
if (options.key && options.cert) {
|
|
|
|
debug('HTTPS WebHook enabled (by key/cert)');
|
|
|
|
this.options.https.key = fs.readFileSync(options.key);
|
|
|
|
this.options.https.cert = fs.readFileSync(options.cert);
|
|
|
|
this._webServer = https.createServer(this.options.https, this._requestListener);
|
|
|
|
} else if (options.pfx) {
|
|
|
|
debug('HTTPS WebHook enabled (by pfx)');
|
|
|
|
this.options.https.pfx = fs.readFileSync(options.pfx);
|
|
|
|
this._webServer = https.createServer(this.options.https, this._requestListener);
|
|
|
|
} else if (options.https) {
|
|
|
|
debug('HTTPS WebHook enabled by (https)');
|
|
|
|
this._webServer = https.createServer(this.options.https, this._requestListener);
|
2016-03-17 02:44:34 +03:00
|
|
|
} else {
|
|
|
|
debug('HTTP WebHook enabled');
|
|
|
|
this._webServer = http.createServer(this._requestListener);
|
|
|
|
}
|
|
|
|
|
|
|
|
this._webServer.listen(options.port, options.host, () => {
|
|
|
|
debug('WebHook listening on port %s', options.port);
|
|
|
|
});
|
2015-07-13 00:24:49 +02:00
|
|
|
}
|
|
|
|
|
2016-03-17 02:44:34 +03:00
|
|
|
// used so that other funcs are not non-optimizable
|
|
|
|
_safeParse(json) {
|
|
|
|
try {
|
|
|
|
return JSON.parse(json);
|
|
|
|
} catch (err) {
|
|
|
|
debug(err);
|
|
|
|
return null;
|
|
|
|
}
|
2015-07-13 00:24:49 +02:00
|
|
|
}
|
|
|
|
|
2017-01-02 13:04:44 +03:00
|
|
|
/**
|
|
|
|
* Handle request body by passing it to 'callback'
|
|
|
|
* @private
|
|
|
|
*/
|
2017-01-06 22:26:25 +03:00
|
|
|
_parseBody(err, body) {
|
2016-03-17 02:44:34 +03:00
|
|
|
if (err) {
|
|
|
|
return debug(err);
|
|
|
|
}
|
2015-07-13 00:24:49 +02:00
|
|
|
|
2016-03-17 02:44:34 +03:00
|
|
|
const data = this._safeParse(body);
|
|
|
|
if (data) {
|
|
|
|
return this.callback(data);
|
|
|
|
}
|
2015-07-13 00:24:49 +02:00
|
|
|
|
2016-03-17 02:44:34 +03:00
|
|
|
return null;
|
2015-07-13 00:24:49 +02:00
|
|
|
}
|
2016-03-17 02:44:34 +03:00
|
|
|
|
2017-01-02 13:04:44 +03:00
|
|
|
/**
|
|
|
|
* Listener for 'request' event on server
|
|
|
|
* @private
|
|
|
|
* @see https://nodejs.org/docs/latest/api/http.html#http_http_createserver_requestlistener
|
|
|
|
* @see https://nodejs.org/docs/latest/api/https.html#https_https_createserver_options_requestlistener
|
|
|
|
*/
|
2017-01-06 22:26:25 +03:00
|
|
|
_requestListener(req, res) {
|
2016-07-13 19:52:50 +02:00
|
|
|
debug('WebHook request URL: %s', req.url);
|
2016-03-17 02:44:34 +03:00
|
|
|
debug('WebHook request headers: %j', req.headers);
|
|
|
|
|
|
|
|
// If there isn't token on URL
|
2017-01-02 13:04:44 +03:00
|
|
|
if (!this._regex.test(req.url)) {
|
2016-03-17 02:44:34 +03:00
|
|
|
debug('WebHook request unauthorized');
|
|
|
|
res.statusCode = 401;
|
|
|
|
res.end();
|
|
|
|
} else if (req.method === 'POST') {
|
|
|
|
req
|
|
|
|
.pipe(bl(this._parseBody))
|
2016-04-25 16:03:36 +09:00
|
|
|
.on('finish', () => res.end('OK'));
|
2016-03-17 02:44:34 +03:00
|
|
|
} else {
|
|
|
|
// Authorized but not a POST
|
|
|
|
debug('WebHook request isn\'t a POST');
|
|
|
|
res.statusCode = 418; // I'm a teabot!
|
|
|
|
res.end();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-02 13:58:46 +03:00
|
|
|
/**
|
|
|
|
* Close the webHook
|
|
|
|
* @return {Promise}
|
|
|
|
*/
|
|
|
|
close() {
|
|
|
|
const self = this;
|
|
|
|
return new Promise(function closePromise(resolve, reject) {
|
|
|
|
self._webServer.close(function closeCb(error) {
|
|
|
|
if (error) return reject(error);
|
|
|
|
return resolve();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2016-03-17 02:44:34 +03:00
|
|
|
}
|
2015-07-13 00:24:49 +02:00
|
|
|
|
|
|
|
module.exports = TelegramBotWebHook;
|