UNPKG

6.22 kBJavaScriptView Raw
1'use strict';
2
3var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
4
5function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
7var errors = require('./errors');
8var debug = require('debug')('node-telegram-bot-api');
9var https = require('https');
10var http = require('http');
11var fs = require('fs');
12var bl = require('bl');
13var Promise = require('bluebird');
14
15var TelegramBotWebHook = function () {
16 /**
17 * Sets up a webhook to receive updates
18 * @param {TelegramBot} bot
19 * @see https://core.telegram.org/bots/api#getting-updates
20 */
21 function TelegramBotWebHook(bot) {
22 _classCallCheck(this, TelegramBotWebHook);
23
24 this.bot = bot;
25 this.options = typeof bot.options.webHook === 'boolean' ? {} : bot.options.webHook;
26 this.options.host = this.options.host || '0.0.0.0';
27 this.options.port = this.options.port || 8443;
28 this.options.https = this.options.https || {};
29 this.options.healthEndpoint = this.options.healthEndpoint || '/healthz';
30 this._healthRegex = new RegExp(this.options.healthEndpoint);
31 this._webServer = null;
32 this._open = false;
33 this._requestListener = this._requestListener.bind(this);
34 this._parseBody = this._parseBody.bind(this);
35
36 if (this.options.key && this.options.cert) {
37 debug('HTTPS WebHook enabled (by key/cert)');
38 this.options.https.key = fs.readFileSync(this.options.key);
39 this.options.https.cert = fs.readFileSync(this.options.cert);
40 this._webServer = https.createServer(this.options.https, this._requestListener);
41 } else if (this.options.pfx) {
42 debug('HTTPS WebHook enabled (by pfx)');
43 this.options.https.pfx = fs.readFileSync(this.options.pfx);
44 this._webServer = https.createServer(this.options.https, this._requestListener);
45 } else if (Object.keys(this.options.https).length) {
46 debug('HTTPS WebHook enabled by (https)');
47 this._webServer = https.createServer(this.options.https, this._requestListener);
48 } else {
49 debug('HTTP WebHook enabled');
50 this._webServer = http.createServer(this._requestListener);
51 }
52 }
53
54 /**
55 * Open WebHook by listening on the port
56 * @return {Promise}
57 */
58
59
60 _createClass(TelegramBotWebHook, [{
61 key: 'open',
62 value: function open() {
63 var _this = this;
64
65 if (this.isOpen()) {
66 return Promise.resolve();
67 }
68 return new Promise(function (resolve) {
69 _this._webServer.listen(_this.options.port, _this.options.host, function () {
70 debug('WebHook listening on port %s', _this.options.port);
71 _this._open = true;
72 return resolve();
73 });
74 });
75 }
76
77 /**
78 * Close the webHook
79 * @return {Promise}
80 */
81
82 }, {
83 key: 'close',
84 value: function close() {
85 var _this2 = this;
86
87 if (!this.isOpen()) {
88 return Promise.resolve();
89 }
90 return new Promise(function (resolve, reject) {
91 _this2._webServer.close(function (error) {
92 if (error) return reject(error);
93 _this2._open = false;
94 return resolve();
95 });
96 });
97 }
98
99 /**
100 * Return `true` if server is listening. Otherwise, `false`.
101 */
102
103 }, {
104 key: 'isOpen',
105 value: function isOpen() {
106 // NOTE: Since `http.Server.listening` was added in v5.7.0
107 // and we still need to support Node v4,
108 // we are going to fallback to 'this._open'.
109 // The following LOC would suffice for newer versions of Node.js
110 // return this._webServer.listening;
111 return this._open;
112 }
113
114 /**
115 * Handle error thrown during processing of webhook request.
116 * @private
117 * @param {Error} error
118 */
119
120 }, {
121 key: '_error',
122 value: function _error(error) {
123 if (!this.bot.listeners('webhook_error').length) {
124 return console.error('error: [webhook_error] %j', error); // eslint-disable-line no-console
125 }
126 return this.bot.emit('webhook_error', error);
127 }
128
129 /**
130 * Handle request body by passing it to 'callback'
131 * @private
132 */
133
134 }, {
135 key: '_parseBody',
136 value: function _parseBody(error, body) {
137 if (error) {
138 return this._error(new errors.FatalError(error));
139 }
140
141 var data = void 0;
142 try {
143 data = JSON.parse(body.toString());
144 } catch (parseError) {
145 return this._error(new errors.ParseError(parseError.message));
146 }
147
148 return this.bot.processUpdate(data);
149 }
150
151 /**
152 * Listener for 'request' event on server
153 * @private
154 * @see https://nodejs.org/docs/latest/api/http.html#http_http_createserver_requestlistener
155 * @see https://nodejs.org/docs/latest/api/https.html#https_https_createserver_options_requestlistener
156 */
157
158 }, {
159 key: '_requestListener',
160 value: function _requestListener(req, res) {
161 debug('WebHook request URL: %s', req.url);
162 debug('WebHook request headers: %j', req.headers);
163
164 if (req.url.indexOf(this.bot.token) !== -1) {
165 if (req.method !== 'POST') {
166 debug('WebHook request isn\'t a POST');
167 res.statusCode = 418; // I'm a teabot!
168 res.end();
169 } else {
170 req.pipe(bl(this._parseBody)).on('finish', function () {
171 return res.end('OK');
172 });
173 }
174 } else if (this._healthRegex.test(req.url)) {
175 debug('WebHook health check passed');
176 res.statusCode = 200;
177 res.end('OK');
178 } else {
179 debug('WebHook request unauthorized');
180 res.statusCode = 401;
181 res.end();
182 }
183 }
184 }]);
185
186 return TelegramBotWebHook;
187}();
188
189module.exports = TelegramBotWebHook;
\No newline at end of file