2
0
mirror of https://github.com/yagop/node-telegram-bot-api synced 2025-08-29 13:27:44 +00:00

Update codebase

Details:

  * Update documentation on constructors and methods
  * Make code more modular
  * Improve code (generally)
This commit is contained in:
GochoMugo 2017-01-02 13:04:44 +03:00
parent 4e5a493cad
commit daab34d98d
No known key found for this signature in database
GPG Key ID: 7B6A01CB57AA39E4
5 changed files with 259 additions and 203 deletions

View File

@ -71,6 +71,7 @@ TelegramBot
* [TelegramBot](#TelegramBot) * [TelegramBot](#TelegramBot)
* [new TelegramBot(token, [options])](#new_TelegramBot_new) * [new TelegramBot(token, [options])](#new_TelegramBot_new)
* [.initPolling()](#TelegramBot+initPolling)
* [.stopPolling()](#TelegramBot+stopPolling) ⇒ <code>Promise</code> * [.stopPolling()](#TelegramBot+stopPolling) ⇒ <code>Promise</code>
* [.getMe()](#TelegramBot+getMe) ⇒ <code>Promise</code> * [.getMe()](#TelegramBot+getMe) ⇒ <code>Promise</code>
* [.setWebHook(url, [cert])](#TelegramBot+setWebHook) * [.setWebHook(url, [cert])](#TelegramBot+setWebHook)
@ -122,14 +123,21 @@ Emits `message` when a message arrives.
| token | <code>String</code> | | Bot Token | | token | <code>String</code> | | Bot Token |
| [options] | <code>Object</code> | | | | [options] | <code>Object</code> | | |
| [options.polling] | <code>Boolean</code> &#124; <code>Object</code> | <code>false</code> | Set true to enable polling or set options | | [options.polling] | <code>Boolean</code> &#124; <code>Object</code> | <code>false</code> | Set true to enable polling or set options |
| [options.polling.timeout] | <code>String</code> &#124; <code>Number</code> | <code>10</code> | Polling time in seconds | | [options.polling.timeout] | <code>String</code> &#124; <code>Number</code> | <code>10</code> | Timeout in seconds for long polling |
| [options.polling.interval] | <code>String</code> &#124; <code>Number</code> | <code>2000</code> | Interval between requests in miliseconds | | [options.polling.interval] | <code>String</code> &#124; <code>Number</code> | <code>300</code> | Interval between requests in miliseconds |
| [options.webHook] | <code>Boolean</code> &#124; <code>Object</code> | <code>false</code> | Set true to enable WebHook or set options | | [options.webHook] | <code>Boolean</code> &#124; <code>Object</code> | <code>false</code> | Set true to enable WebHook or set options |
| [options.webHook.key] | <code>String</code> | | PEM private key to webHook server. | | [options.webHook.port] | <code>Number</code> | <code>8443</code> | Port to bind to |
| [options.webHook.cert] | <code>String</code> | | PEM certificate (public) to webHook server. | | [options.webHook.key] | <code>String</code> | | Path to file with PEM private key for webHook server. (Read synchronously!) |
| [options.webHook.cert] | <code>String</code> | | Path to file with PEM certificate (public) for webHook server. (Read synchronously!) |
| [options.onlyFirstMatch] | <code>Boolean</code> | <code>false</code> | Set to true to stop after first match. Otherwise, all regexps are executed | | [options.onlyFirstMatch] | <code>Boolean</code> | <code>false</code> | Set to true to stop after first match. Otherwise, all regexps are executed |
| [options.request] | <code>Object</code> | | Options which will be added for all requests to telegram api. See https://github.com/request/request#requestoptions-callback for more information. | | [options.request] | <code>Object</code> | | Options which will be added for all requests to telegram api. See https://github.com/request/request#requestoptions-callback for more information. |
<a name="TelegramBot+initPolling"></a>
### telegramBot.initPolling()
Start polling
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
<a name="TelegramBot+stopPolling"></a> <a name="TelegramBot+stopPolling"></a>
### telegramBot.stopPolling() ⇒ <code>Promise</code> ### telegramBot.stopPolling() ⇒ <code>Promise</code>

View File

@ -14,7 +14,8 @@
"bot" "bot"
], ],
"scripts": { "scripts": {
"prepublish": "babel -d ./lib src", "build": "babel -d ./lib src",
"prepublish": "npm run build",
"test": "istanbul cover ./node_modules/mocha/bin/_mocha -- -R spec --timeout 10000", "test": "istanbul cover ./node_modules/mocha/bin/_mocha -- -R spec --timeout 10000",
"prepublish:test": "npm run prepublish && npm run test", "prepublish:test": "npm run prepublish && npm run test",
"gen-doc": "jsdoc2md --src src/telegram.js -t README.hbs > README.md", "gen-doc": "jsdoc2md --src src/telegram.js -t README.hbs > README.md",

View File

@ -20,6 +20,11 @@ const _messageTypes = [
'new_chat_photo', 'delete_chat_photo', 'group_chat_created' 'new_chat_photo', 'delete_chat_photo', 'group_chat_created'
]; ];
// enable cancellation
Promise.config({
cancellation: true,
});
class TelegramBot extends EventEmitter { class TelegramBot extends EventEmitter {
static get messageTypes() { static get messageTypes() {
@ -36,22 +41,22 @@ class TelegramBot extends EventEmitter {
* @param {String} token Bot Token * @param {String} token Bot Token
* @param {Object} [options] * @param {Object} [options]
* @param {Boolean|Object} [options.polling=false] Set true to enable polling or set options * @param {Boolean|Object} [options.polling=false] Set true to enable polling or set options
* @param {String|Number} [options.polling.timeout=10] Polling time in seconds * @param {String|Number} [options.polling.timeout=10] Timeout in seconds for long polling
* @param {String|Number} [options.polling.interval=2000] Interval between requests in miliseconds * @param {String|Number} [options.polling.interval=300] Interval between requests in miliseconds
* @param {Boolean|Object} [options.webHook=false] Set true to enable WebHook or set options * @param {Boolean|Object} [options.webHook=false] Set true to enable WebHook or set options
* @param {String} [options.webHook.key] PEM private key to webHook server. * @param {Number} [options.webHook.port=8443] Port to bind to
* @param {String} [options.webHook.cert] PEM certificate (public) to webHook server. * @param {String} [options.webHook.key] Path to file with PEM private key for webHook server. (Read synchronously!)
* @param {String} [options.webHook.cert] Path to file with PEM certificate (public) for webHook server. (Read synchronously!)
* @param {Boolean} [options.onlyFirstMatch=false] Set to true to stop after first match. Otherwise, all regexps are executed * @param {Boolean} [options.onlyFirstMatch=false] Set to true to stop after first match. Otherwise, all regexps are executed
* @param {Object} [options.request] Options which will be added for all requests to telegram api. * @param {Object} [options.request] Options which will be added for all requests to telegram api. See https://github.com/request/request#requestoptions-callback for more information.
* See https://github.com/request/request#requestoptions-callback for more information.
* @see https://core.telegram.org/bots/api * @see https://core.telegram.org/bots/api
*/ */
constructor(token, options = {}) { constructor(token, options = {}) {
super(); super();
this.options = options;
this.token = token; this.token = token;
this.textRegexpCallbacks = []; this.options = options;
this.onReplyToMessages = []; this._textRegexpCallbacks = [];
this._onReplyToMessages = [];
if (options.polling) { if (options.polling) {
this.initPolling(); this.initPolling();
@ -62,27 +67,13 @@ class TelegramBot extends EventEmitter {
} }
} }
initPolling() {
if (this._polling) {
this._polling.abort = true;
this._polling.lastRequest.cancel('Polling restart');
}
this._polling = new TelegramBotPolling(this.token, this.options.polling, this.processUpdate.bind(this));
}
/** /**
* Stops polling after the last polling request resolves * Process an update; emitting the proper events and executing regexp
* * callbacks
* @return {Promise} promise Promise, of last polling request * @param {Object} update
* @private
*/ */
stopPolling() { _processUpdate(update) {
if (this._polling) {
return this._polling.stopPolling();
}
return Promise.resolve();
}
processUpdate(update) {
debug('Process Update %j', update); debug('Process Update %j', update);
const message = update.message; const message = update.message;
const editedMessage = update.edited_message; const editedMessage = update.edited_message;
@ -97,27 +88,28 @@ class TelegramBot extends EventEmitter {
this.emit('message', message); this.emit('message', message);
const processMessageType = messageType => { const processMessageType = messageType => {
if (message[messageType]) { if (message[messageType]) {
debug('Emtting %s: %j', messageType, message); debug('Emitting %s: %j', messageType, message);
this.emit(messageType, message); this.emit(messageType, message);
} }
}; };
TelegramBot.messageTypes.forEach(processMessageType); TelegramBot.messageTypes.forEach(processMessageType);
if (message.text) { if (message.text) {
debug('Text message'); debug('Text message');
this.textRegexpCallbacks.some(reg => { this._textRegexpCallbacks.some(reg => {
debug('Matching %s with %s', message.text, reg.regexp); debug('Matching %s with %s', message.text, reg.regexp);
const result = reg.regexp.exec(message.text); const result = reg.regexp.exec(message.text);
if (result) { if (!result) {
debug('Matches %s', reg.regexp); return false;
reg.callback(message, result);
// returning truthy value exits .some
return this.options.onlyFirstMatch;
} }
debug('Matches %s', reg.regexp);
reg.callback(message, result);
// returning truthy value exits .some
return this.options.onlyFirstMatch;
}); });
} }
if (message.reply_to_message) { if (message.reply_to_message) {
// Only callbacks waiting for this message // Only callbacks waiting for this message
this.onReplyToMessages.forEach(reply => { this._onReplyToMessages.forEach(reply => {
// Message from the same chat // Message from the same chat
if (reply.chatId === message.chat.id) { if (reply.chatId === message.chat.id) {
// Responding to that message // Responding to that message
@ -139,7 +131,7 @@ class TelegramBot extends EventEmitter {
} }
} else if (channelPost) { } else if (channelPost) {
debug('Process Update channel_post %j', channelPost); debug('Process Update channel_post %j', channelPost);
this.emit('channel_post', channelPost); this.emit('channel_post', channelPost);
} else if (editedChannelPost) { } else if (editedChannelPost) {
debug('Process Update edited_channel_post %j', editedChannelPost); debug('Process Update edited_channel_post %j', editedChannelPost);
this.emit('edited_channel_post', editedChannelPost); this.emit('edited_channel_post', editedChannelPost);
@ -148,7 +140,7 @@ class TelegramBot extends EventEmitter {
} }
if (editedChannelPost.caption) { if (editedChannelPost.caption) {
this.emit('edited_channel_post_caption', editedChannelPost); this.emit('edited_channel_post_caption', editedChannelPost);
} }
} else if (inlineQuery) { } else if (inlineQuery) {
debug('Process Update inline_query %j', inlineQuery); debug('Process Update inline_query %j', inlineQuery);
this.emit('inline_query', inlineQuery); this.emit('inline_query', inlineQuery);
@ -161,24 +153,42 @@ class TelegramBot extends EventEmitter {
} }
} }
// used so that other funcs are not non-optimizable /**
_safeParse(json) { * Generates url with bot token and provided path/method you want to be got/executed by bot
try { * @param {String} path
return JSON.parse(json); * @return {String} url
} catch (err) { * @private
throw new Error(`Error parsing Telegram response: ${String(json)}`); * @see https://core.telegram.org/bots/api#making-requests
} */
_buildURL(_path) {
return URL.format({
protocol: 'https',
host: 'api.telegram.org',
pathname: `/bot${this.token}/${_path}`
});
} }
/**
* Fix 'reply_markup' parameter by making it JSON-serialized, as
* required by the Telegram Bot API
* @param {Object} obj Object; either 'form' or 'qs'
* @private
* @see https://core.telegram.org/bots/api#sendmessage
*/
_fixReplyMarkup(obj) { _fixReplyMarkup(obj) {
const replyMarkup = obj.reply_markup; const replyMarkup = obj.reply_markup;
if (replyMarkup && typeof replyMarkup !== 'string') { if (replyMarkup && typeof replyMarkup !== 'string') {
// reply_markup must be passed as JSON stringified to Telegram
obj.reply_markup = JSON.stringify(replyMarkup); obj.reply_markup = JSON.stringify(replyMarkup);
} }
} }
// request-promise /**
* Make request against the API
* @param {String} _path API endpoint
* @param {Object} [options]
* @private
* @return {Promise}
*/
_request(_path, options = {}) { _request(_path, options = {}) {
if (!this.token) { if (!this.token) {
throw new Error('Telegram Bot Token not provided!'); throw new Error('Telegram Bot Token not provided!');
@ -194,6 +204,7 @@ class TelegramBot extends EventEmitter {
if (options.qs) { if (options.qs) {
this._fixReplyMarkup(options.qs); this._fixReplyMarkup(options.qs);
} }
options.url = this._buildURL(_path); options.url = this._buildURL(_path);
options.simple = false; options.simple = false;
options.resolveWithFullResponse = true; options.resolveWithFullResponse = true;
@ -202,31 +213,108 @@ class TelegramBot extends EventEmitter {
return request(options) return request(options)
.then(resp => { .then(resp => {
if (resp.statusCode !== 200) { if (resp.statusCode !== 200) {
throw new Error(`${resp.statusCode} ${resp.body}`); const error = new Error(`${resp.statusCode} ${resp.body}`);
error.response = resp;
throw error;
}
let data;
try {
data = JSON.parse(resp.body);
} catch (err) {
const error = new Error(`Error parsing Telegram response: ${resp.body}`);
error.response = resp;
throw error;
} }
const data = this._safeParse(resp.body);
if (data.ok) { if (data.ok) {
return data.result; return data.result;
} }
throw new Error(`${data.error_code} ${data.description}`); const error = new Error(`${data.error_code} ${data.description}`);
error.response = resp;
error.response.body = data;
throw error;
}); });
} }
/** /**
* Generates url with bot token and provided path/method you want to be got/executed by bot * Format data to be uploaded; handles file paths, streams and buffers
* @return {String} url * @param {String} type
* @param {String} path * @param {String|stream.Stream|Buffer} data
* @return {Array} formatted
* @return {Object} formatted[0] formData
* @return {String} formatted[1] fileId
* @private * @private
* @see https://core.telegram.org/bots/api#making-requests
*/ */
_buildURL(_path) { _formatSendData(type, data) {
return URL.format({ let formData;
protocol: 'https', let fileName;
host: 'api.telegram.org', let fileId;
pathname: `/bot${this.token}/${_path}` if (data instanceof stream.Stream) {
}); fileName = URL.parse(path.basename(data.path.toString())).pathname;
formData = {};
formData[type] = {
value: data,
options: {
filename: qs.unescape(fileName),
contentType: mime.lookup(fileName)
}
};
} else if (Buffer.isBuffer(data)) {
const filetype = fileType(data);
if (!filetype) {
throw new Error('Unsupported Buffer file type');
}
formData = {};
formData[type] = {
value: data,
options: {
filename: `data.${filetype.ext}`,
contentType: filetype.mime
}
};
} else if (fs.existsSync(data)) {
fileName = path.basename(data);
formData = {};
formData[type] = {
value: fs.createReadStream(data),
options: {
filename: fileName,
contentType: mime.lookup(fileName)
}
};
} else {
fileId = data;
}
return [formData, fileId];
}
/**
* Start polling
*/
initPolling() {
if (this._polling) {
this._polling.stopPolling({
cancel: true,
reason: 'Polling restart',
});
}
this._polling = new TelegramBotPolling(this._request.bind(this), this.options.polling, this._processUpdate.bind(this));
}
/**
* Stops polling after the last polling request resolves
* @return {Promise} promise Promise, of last polling request
*/
stopPolling() {
if (!this._polling) {
return Promise.resolve();
}
const polling = this._polling;
delete this._polling;
return polling.stopPolling();
} }
/** /**
@ -330,49 +418,6 @@ class TelegramBot extends EventEmitter {
return this._request('forwardMessage', { form }); return this._request('forwardMessage', { form });
} }
_formatSendData(type, data) {
let formData;
let fileName;
let fileId;
if (data instanceof stream.Stream) {
fileName = URL.parse(path.basename(data.path.toString())).pathname;
formData = {};
formData[type] = {
value: data,
options: {
filename: qs.unescape(fileName),
contentType: mime.lookup(fileName)
}
};
} else if (Buffer.isBuffer(data)) {
const filetype = fileType(data);
if (!filetype) {
throw new Error('Unsupported Buffer file type');
}
formData = {};
formData[type] = {
value: data,
options: {
filename: `data.${filetype.ext}`,
contentType: filetype.mime
}
};
} else if (fs.existsSync(data)) {
fileName = path.basename(data);
formData = {};
formData[type] = {
value: fs.createReadStream(data),
options: {
filename: fileName,
contentType: mime.lookup(fileName)
}
};
} else {
fileId = data;
}
return [formData, fileId];
}
/** /**
* Send photo * Send photo
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
@ -776,7 +821,7 @@ class TelegramBot extends EventEmitter {
* the `msg` and the result of executing `regexp.exec` on message text. * the `msg` and the result of executing `regexp.exec` on message text.
*/ */
onText(regexp, callback) { onText(regexp, callback) {
this.textRegexpCallbacks.push({ regexp, callback }); this._textRegexpCallbacks.push({ regexp, callback });
} }
/** /**
@ -787,7 +832,7 @@ class TelegramBot extends EventEmitter {
* message. * message.
*/ */
onReplyToMessage(chatId, messageId, callback) { onReplyToMessage(chatId, messageId, callback) {
this.onReplyToMessages.push({ this._onReplyToMessages.push({
chatId, chatId,
messageId, messageId,
callback callback

View File

@ -1,48 +1,69 @@
const Promise = require('bluebird');
const debug = require('debug')('node-telegram-bot-api'); const debug = require('debug')('node-telegram-bot-api');
const request = require('request-promise');
const URL = require('url');
const ANOTHER_WEB_HOOK_USED = 409; const ANOTHER_WEB_HOOK_USED = 409;
class TelegramBotPolling { class TelegramBotPolling {
/**
constructor(token, options = {}, callback) { * Handles polling against the Telegram servers.
// enable cancellation *
Promise.config({ * @param {Function} request Function used to make HTTP requests
cancellation: true, * @param {Boolean|Object} options Polling options
}); * @param {Number} [options.timeout=10] Timeout in seconds for long polling
* @param {Number} [options.interval=300] Interval between requests in milliseconds
* @param {Function} callback Function for processing a new update
* @see https://core.telegram.org/bots/api#getupdates
*/
constructor(request, options = {}, callback) {
/* eslint-disable no-param-reassign */
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options; // eslint-disable-line no-param-reassign callback = options;
options = {}; // eslint-disable-line no-param-reassign options = {};
} else if (typeof options === 'boolean') {
options = {};
} }
/* eslint-enable no-param-reassign */
this.offset = 0; this.request = request;
this.token = token; this.options = options;
this.options.timeout = options.timeout || 10;
this.options.interval = (typeof options.interval === 'number') ? options.interval : 300;
this.callback = callback; this.callback = callback;
this.timeout = options.timeout || 10; this._offset = 0;
this.interval = (typeof options.interval === 'number') ? options.interval : 300; this._lastUpdate = 0;
this.lastUpdate = 0; this._lastRequest = null;
this.lastRequest = null; this._abort = false;
this.abort = false;
this._polling(); this._polling();
} }
stopPolling() { /**
this.abort = true; * Stop polling
* @param {Object} [options]
* @param {Boolean} [options.cancel] Cancel current request
* @param {String} [options.reason] Reason for stopping polling
*/
stopPolling(options = {}) {
this._abort = true;
if (options.cancel) {
const reason = options.reason || 'Polling stop';
return this._lastRequest.cancel(reason);
}
// wait until the last request is fulfilled // wait until the last request is fulfilled
return this.lastRequest; return this._lastRequest;
} }
/**
* Invokes polling (with recursion!)
* @private
*/
_polling() { _polling() {
this.lastRequest = this this._lastRequest = this
._getUpdates() ._getUpdates()
.then(updates => { .then(updates => {
this.lastUpdate = Date.now(); this._lastUpdate = Date.now();
debug('polling data %j', updates); debug('polling data %j', updates);
updates.forEach(update => { updates.forEach(update => {
this.offset = update.update_id; this._offset = update.update_id;
debug('updated offset: %s', this.offset); debug('updated offset: %s', this._offset);
this.callback(update); this.callback(update);
}); });
}) })
@ -51,83 +72,46 @@ class TelegramBotPolling {
throw err; throw err;
}) })
.finally(() => { .finally(() => {
if (this.abort) { if (this._abort) {
debug('Polling is aborted!'); debug('Polling is aborted!');
} else { } else {
debug('setTimeout for %s miliseconds', this.interval); debug('setTimeout for %s miliseconds', this.options.interval);
setTimeout(() => this._polling(), this.interval); setTimeout(() => this._polling(), this.options.interval);
} }
}); });
} }
// used so that other funcs are not non-optimizable /**
_safeParse(json) { * Unset current webhook. Used when we detect that a webhook has been set
try { * and we are trying to poll. Polling and WebHook are mutually exclusive.
return JSON.parse(json); * @see https://core.telegram.org/bots/api#getting-updates
} catch (err) { * @private
throw new Error(`Error parsing Telegram response: ${String(json)}`); */
}
}
_unsetWebHook() { _unsetWebHook() {
return request({ return this.request('setWebHook');
url: URL.format({
protocol: 'https',
host: 'api.telegram.org',
pathname: `/bot${this.token}/setWebHook`
}),
simple: false,
resolveWithFullResponse: true
})
.promise()
.then(resp => {
if (!resp) {
throw new Error(resp);
}
return [];
});
} }
/**
* Retrieve updates
*/
_getUpdates() { _getUpdates() {
const opts = { const opts = {
qs: { qs: {
offset: this.offset + 1, offset: this._offset + 1,
limit: this.limit, limit: this.options.limit,
timeout: this.timeout timeout: this.options.timeout
}, },
url: URL.format({
protocol: 'https',
host: 'api.telegram.org',
pathname: `/bot${this.token}/getUpdates`
}),
simple: false,
resolveWithFullResponse: true,
forever: true,
}; };
debug('polling with options: %j', opts); debug('polling with options: %j', opts);
return request(opts) return this.request('getUpdates', opts)
.promise() .catch(err => {
.timeout((10 + this.timeout) * 1000) if (err.response.statusCode === ANOTHER_WEB_HOOK_USED) {
.then(resp => {
if (resp.statusCode === ANOTHER_WEB_HOOK_USED) {
return this._unsetWebHook(); return this._unsetWebHook();
} }
throw err;
if (resp.statusCode !== 200) {
throw new Error(`${resp.statusCode} ${resp.body}`);
}
const data = this._safeParse(resp.body);
if (data.ok) {
return data.result;
}
throw new Error(`${data.error_code} ${data.description}`);
}); });
} }
} }
module.exports = TelegramBotPolling; module.exports = TelegramBotPolling;

View File

@ -4,18 +4,28 @@ const http = require('http');
const fs = require('fs'); const fs = require('fs');
const bl = require('bl'); const bl = require('bl');
class TelegramBotWebHook { 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
*/
constructor(token, options, callback) { constructor(token, options, callback) {
this.token = token;
this.callback = callback;
this.regex = new RegExp(this.token);
// define opts // define opts
if (typeof options === 'boolean') { if (typeof options === 'boolean') {
options = {}; // eslint-disable-line no-param-reassign options = {}; // eslint-disable-line no-param-reassign
} }
options.port = options.port || 8443;
this.token = token;
this.options = options;
this.options.port = options.port || 8443;
this.callback = callback;
this._regex = new RegExp(this.token);
this._webServer = null;
if (options.key && options.cert) { // HTTPS Server if (options.key && options.cert) { // HTTPS Server
debug('HTTPS WebHook enabled'); debug('HTTPS WebHook enabled');
@ -44,7 +54,10 @@ class TelegramBotWebHook {
} }
} }
// pipe+parse body /**
* Handle request body by passing it to 'callback'
* @private
*/
_parseBody = (err, body) => { _parseBody = (err, body) => {
if (err) { if (err) {
return debug(err); return debug(err);
@ -58,13 +71,18 @@ class TelegramBotWebHook {
return null; return null;
} }
// bound req listener /**
* 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
*/
_requestListener = (req, res) => { _requestListener = (req, res) => {
debug('WebHook request URL: %s', req.url); debug('WebHook request URL: %s', req.url);
debug('WebHook request headers: %j', req.headers); debug('WebHook request headers: %j', req.headers);
// If there isn't token on URL // If there isn't token on URL
if (!this.regex.test(req.url)) { if (!this._regex.test(req.url)) {
debug('WebHook request unauthorized'); debug('WebHook request unauthorized');
res.statusCode = 401; res.statusCode = 401;
res.end(); res.end();