You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
node-telegram-bot-api/src/telegramPolling.js

119 lines
3.3 KiB

const debug = require('debug')('node-telegram-bot-api');
const ANOTHER_WEB_HOOK_USED = 409;
class TelegramBotPolling {
/**
* Handles polling against the Telegram servers.
*
* @param {Function} request Function used to make HTTP requests
* @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') {
callback = options;
options = {};
} else if (typeof options === 'boolean') {
options = {};
}
/* eslint-enable no-param-reassign */
this.request = request;
this.options = options;
this.options.timeout = options.timeout || 10;
this.options.interval = (typeof options.interval === 'number') ? options.interval : 300;
this.callback = callback;
this._offset = 0;
this._lastUpdate = 0;
this._lastRequest = null;
this._abort = false;
this._pollingTimeout = null;
this._polling();
}
/**
* 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;
clearTimeout(this._pollingTimeout);
if (options.cancel) {
const reason = options.reason || 'Polling stop';
return this._lastRequest.cancel(reason);
}
// wait until the last request is fulfilled
return this._lastRequest;
}
/**
* Invokes polling (with recursion!)
* @private
*/
_polling() {
this._lastRequest = this
._getUpdates()
.then(updates => {
this._lastUpdate = Date.now();
debug('polling data %j', updates);
updates.forEach(update => {
this._offset = update.update_id;
debug('updated offset: %s', this._offset);
this.callback(update);
});
})
.catch(err => {
debug('polling error: %s', err.message);
throw err;
})
.finally(() => {
if (this._abort) {
debug('Polling is aborted!');
} else {
debug('setTimeout for %s miliseconds', this.options.interval);
this._pollingTimeout = setTimeout(() => this._polling(), this.options.interval);
}
});
}
/**
* Unset current webhook. Used when we detect that a webhook has been set
* and we are trying to poll. Polling and WebHook are mutually exclusive.
* @see https://core.telegram.org/bots/api#getting-updates
* @private
*/
_unsetWebHook() {
return this.request('setWebHook');
}
/**
* Retrieve updates
*/
_getUpdates() {
const opts = {
qs: {
offset: this._offset + 1,
limit: this.options.limit,
timeout: this.options.timeout
},
};
debug('polling with options: %j', opts);
return this.request('getUpdates', opts)
.catch(err => {
if (err.response.statusCode === ANOTHER_WEB_HOOK_USED) {
return this._unsetWebHook();
}
throw err;
});
}
}
module.exports = TelegramBotPolling;