1 | const errors = require('./errors');
|
2 | const debug = require('debug')('node-telegram-bot-api');
|
3 | const https = require('https');
|
4 | const http = require('http');
|
5 | const fs = require('fs');
|
6 | const bl = require('bl');
|
7 | const Promise = require('bluebird');
|
8 |
|
9 |
|
10 | class TelegramBotWebHook {
|
11 | |
12 |
|
13 |
|
14 |
|
15 |
|
16 | constructor(bot) {
|
17 | this.bot = bot;
|
18 | this.options = (typeof bot.options.webHook === 'boolean') ? {} : bot.options.webHook;
|
19 | this.options.host = this.options.host || '0.0.0.0';
|
20 | this.options.port = this.options.port || 8443;
|
21 | this.options.https = this.options.https || {};
|
22 | this.options.healthEndpoint = this.options.healthEndpoint || '/healthz';
|
23 | this._healthRegex = new RegExp(this.options.healthEndpoint);
|
24 | this._webServer = null;
|
25 | this._open = false;
|
26 | this._requestListener = this._requestListener.bind(this);
|
27 | this._parseBody = this._parseBody.bind(this);
|
28 |
|
29 | if (this.options.key && this.options.cert) {
|
30 | debug('HTTPS WebHook enabled (by key/cert)');
|
31 | this.options.https.key = fs.readFileSync(this.options.key);
|
32 | this.options.https.cert = fs.readFileSync(this.options.cert);
|
33 | this._webServer = https.createServer(this.options.https, this._requestListener);
|
34 | } else if (this.options.pfx) {
|
35 | debug('HTTPS WebHook enabled (by pfx)');
|
36 | this.options.https.pfx = fs.readFileSync(this.options.pfx);
|
37 | this._webServer = https.createServer(this.options.https, this._requestListener);
|
38 | } else if (Object.keys(this.options.https).length) {
|
39 | debug('HTTPS WebHook enabled by (https)');
|
40 | this._webServer = https.createServer(this.options.https, this._requestListener);
|
41 | } else {
|
42 | debug('HTTP WebHook enabled');
|
43 | this._webServer = http.createServer(this._requestListener);
|
44 | }
|
45 | }
|
46 |
|
47 | |
48 |
|
49 |
|
50 |
|
51 | open() {
|
52 | if (this.isOpen()) {
|
53 | return Promise.resolve();
|
54 | }
|
55 | return new Promise(resolve => {
|
56 | this._webServer.listen(this.options.port, this.options.host, () => {
|
57 | debug('WebHook listening on port %s', this.options.port);
|
58 | this._open = true;
|
59 | return resolve();
|
60 | });
|
61 | });
|
62 | }
|
63 |
|
64 | |
65 |
|
66 |
|
67 |
|
68 | close() {
|
69 | if (!this.isOpen()) {
|
70 | return Promise.resolve();
|
71 | }
|
72 | return new Promise((resolve, reject) => {
|
73 | this._webServer.close(error => {
|
74 | if (error) return reject(error);
|
75 | this._open = false;
|
76 | return resolve();
|
77 | });
|
78 | });
|
79 | }
|
80 |
|
81 | |
82 |
|
83 |
|
84 | isOpen() {
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 | return this._open;
|
91 | }
|
92 |
|
93 | |
94 |
|
95 |
|
96 |
|
97 |
|
98 | _error(error) {
|
99 | if (!this.bot.listeners('webhook_error').length) {
|
100 | return console.error('error: [webhook_error] %j', error);
|
101 | }
|
102 | return this.bot.emit('webhook_error', error);
|
103 | }
|
104 |
|
105 | |
106 |
|
107 |
|
108 |
|
109 | _parseBody(error, body) {
|
110 | if (error) {
|
111 | return this._error(new errors.FatalError(error));
|
112 | }
|
113 |
|
114 | let data;
|
115 | try {
|
116 | data = JSON.parse(body.toString());
|
117 | } catch (parseError) {
|
118 | return this._error(new errors.ParseError(parseError.message));
|
119 | }
|
120 |
|
121 | return this.bot.processUpdate(data);
|
122 | }
|
123 |
|
124 | |
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 | _requestListener(req, res) {
|
131 | debug('WebHook request URL: %s', req.url);
|
132 | debug('WebHook request headers: %j', req.headers);
|
133 |
|
134 | if (req.url.indexOf(this.bot.token) !== -1) {
|
135 | if (req.method !== 'POST') {
|
136 | debug('WebHook request isn\'t a POST');
|
137 | res.statusCode = 418;
|
138 | res.end();
|
139 | } else {
|
140 | req
|
141 | .pipe(bl(this._parseBody))
|
142 | .on('finish', () => res.end('OK'));
|
143 | }
|
144 | } else if (this._healthRegex.test(req.url)) {
|
145 | debug('WebHook health check passed');
|
146 | res.statusCode = 200;
|
147 | res.end('OK');
|
148 | } else {
|
149 | debug('WebHook request unauthorized');
|
150 | res.statusCode = 401;
|
151 | res.end();
|
152 | }
|
153 | }
|
154 | }
|
155 |
|
156 | module.exports = TelegramBotWebHook;
|