mirror of
https://github.com/yagop/node-telegram-bot-api
synced 2025-08-29 21:37:58 +00:00
src/polling: Fix the Offset Infinite Loop bug (#265)
References: * BR: https://github.com/yagop/node-telegram-bot-api/issues/36
This commit is contained in:
parent
fb1f4344b3
commit
0870684d83
@ -26,6 +26,7 @@ Changed:
|
|||||||
|
|
||||||
Fixed:
|
Fixed:
|
||||||
|
|
||||||
|
1. (#265) Fix the offset infinite loop bug (#36) (by @GochoMugo)
|
||||||
1. Fix game example (by @MCSH)
|
1. Fix game example (by @MCSH)
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,6 +122,7 @@ Emits `message` when a message arrives.
|
|||||||
| [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. |
|
||||||
| [options.baseApiUrl] | <code>String</code> | <code>https://api.telegram.org</code> | API Base URl; useful for proxying and testing |
|
| [options.baseApiUrl] | <code>String</code> | <code>https://api.telegram.org</code> | API Base URl; useful for proxying and testing |
|
||||||
| [options.filepath] | <code>Boolean</code> | <code>true</code> | Allow passing file-paths as arguments when sending files, such as photos using `TelegramBot#sendPhoto()`. See [usage information][usage-sending-files-performance] for more information on this option and its consequences. |
|
| [options.filepath] | <code>Boolean</code> | <code>true</code> | Allow passing file-paths as arguments when sending files, such as photos using `TelegramBot#sendPhoto()`. See [usage information][usage-sending-files-performance] for more information on this option and its consequences. |
|
||||||
|
| [options.badRejection] | <code>Boolean</code> | <code>false</code> | Set to `true` **if and only if** the Node.js version you're using terminates the process on unhandled rejections. This option is only for *forward-compatibility purposes*. |
|
||||||
|
|
||||||
<a name="TelegramBot+on"></a>
|
<a name="TelegramBot+on"></a>
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ that emits the following events:
|
|||||||
1. `pre_checkout_query`: Received a new incoming pre-checkout query
|
1. `pre_checkout_query`: Received a new incoming pre-checkout query
|
||||||
1. `polling_error`: Error occurred during polling. See [polling errors](#polling-errors).
|
1. `polling_error`: Error occurred during polling. See [polling errors](#polling-errors).
|
||||||
1. `webhook_error`: Error occurred handling a webhook request. See [webhook errors](#webhook-errors).
|
1. `webhook_error`: Error occurred handling a webhook request. See [webhook errors](#webhook-errors).
|
||||||
|
1. `error`: Unexpected error occurred, usually fatal!
|
||||||
|
|
||||||
**Tip:** Its much better to listen a specific event rather than on
|
**Tip:** Its much better to listen a specific event rather than on
|
||||||
`message` in order to stay safe from the content.
|
`message` in order to stay safe from the content.
|
||||||
|
@ -174,6 +174,10 @@ class TelegramBot extends EventEmitter {
|
|||||||
* @param {Boolean} [options.filepath=true] Allow passing file-paths as arguments when sending files,
|
* @param {Boolean} [options.filepath=true] Allow passing file-paths as arguments when sending files,
|
||||||
* such as photos using `TelegramBot#sendPhoto()`. See [usage information][usage-sending-files-performance]
|
* such as photos using `TelegramBot#sendPhoto()`. See [usage information][usage-sending-files-performance]
|
||||||
* for more information on this option and its consequences.
|
* for more information on this option and its consequences.
|
||||||
|
* @param {Boolean} [options.badRejection=false] Set to `true`
|
||||||
|
* **if and only if** the Node.js version you're using terminates the
|
||||||
|
* process on unhandled rejections. This option is only for
|
||||||
|
* *forward-compatibility purposes*.
|
||||||
* @see https://core.telegram.org/bots/api
|
* @see https://core.telegram.org/bots/api
|
||||||
*/
|
*/
|
||||||
constructor(token, options = {}) {
|
constructor(token, options = {}) {
|
||||||
@ -184,6 +188,7 @@ class TelegramBot extends EventEmitter {
|
|||||||
this.options.webHook = (typeof options.webHook === 'undefined') ? false : options.webHook;
|
this.options.webHook = (typeof options.webHook === 'undefined') ? false : options.webHook;
|
||||||
this.options.baseApiUrl = options.baseApiUrl || 'https://api.telegram.org';
|
this.options.baseApiUrl = options.baseApiUrl || 'https://api.telegram.org';
|
||||||
this.options.filepath = (typeof options.filepath === 'undefined') ? true : options.filepath;
|
this.options.filepath = (typeof options.filepath === 'undefined') ? true : options.filepath;
|
||||||
|
this.options.badRejection = (typeof options.badRejection === 'undefined') ? false : options.badRejection;
|
||||||
this._textRegexpCallbacks = [];
|
this._textRegexpCallbacks = [];
|
||||||
this._replyListenerId = 0;
|
this._replyListenerId = 0;
|
||||||
this._replyListeners = [];
|
this._replyListeners = [];
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
const errors = require('./errors');
|
||||||
const debug = require('debug')('node-telegram-bot-api');
|
const debug = require('debug')('node-telegram-bot-api');
|
||||||
const deprecate = require('depd')('node-telegram-bot-api');
|
const deprecate = require('depd')('node-telegram-bot-api');
|
||||||
const ANOTHER_WEB_HOOK_USED = 409;
|
const ANOTHER_WEB_HOOK_USED = 409;
|
||||||
@ -79,6 +80,18 @@ class TelegramBotPolling {
|
|||||||
return !!this._lastRequest;
|
return !!this._lastRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle error thrown during polling.
|
||||||
|
* @private
|
||||||
|
* @param {Error} error
|
||||||
|
*/
|
||||||
|
_error(error) {
|
||||||
|
if (!this.bot.listeners('polling_error').length) {
|
||||||
|
return console.error('error: [polling_error] %j', error); // eslint-disable-line no-console
|
||||||
|
}
|
||||||
|
return this.bot.emit('polling_error', error);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes polling (with recursion!)
|
* Invokes polling (with recursion!)
|
||||||
* @return {Promise} promise of the current request
|
* @return {Promise} promise of the current request
|
||||||
@ -93,18 +106,59 @@ class TelegramBotPolling {
|
|||||||
updates.forEach(update => {
|
updates.forEach(update => {
|
||||||
this.options.params.offset = update.update_id + 1;
|
this.options.params.offset = update.update_id + 1;
|
||||||
debug('updated offset: %s', this.options.params.offset);
|
debug('updated offset: %s', this.options.params.offset);
|
||||||
this.bot.processUpdate(update);
|
try {
|
||||||
|
this.bot.processUpdate(update);
|
||||||
|
} catch (err) {
|
||||||
|
err._processing = true;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
debug('polling error: %s', err.message);
|
debug('polling error: %s', err.message);
|
||||||
if (this.bot.listeners('polling_error').length) {
|
if (!err._processing) {
|
||||||
this.bot.emit('polling_error', err);
|
return this._error(err);
|
||||||
} else {
|
|
||||||
console.error('error: [polling_error] %j', err); // eslint-disable-line no-console
|
|
||||||
}
|
}
|
||||||
return null;
|
delete err._processing;
|
||||||
|
/*
|
||||||
|
* An error occured while processing the items,
|
||||||
|
* i.e. in `this.bot.processUpdate()` above.
|
||||||
|
* We need to mark the already-processed items
|
||||||
|
* to avoid fetching them again once the application
|
||||||
|
* is restarted, or moves to next polling interval
|
||||||
|
* (in cases where unhandled rejections do not terminate
|
||||||
|
* the process).
|
||||||
|
* See https://github.com/yagop/node-telegram-bot-api/issues/36#issuecomment-268532067
|
||||||
|
*/
|
||||||
|
if (!this.bot.options.badRejection) {
|
||||||
|
return this._error(err);
|
||||||
|
}
|
||||||
|
const opts = {
|
||||||
|
offset: this.options.params.offset,
|
||||||
|
limit: 1,
|
||||||
|
timeout: 0,
|
||||||
|
};
|
||||||
|
return this.bot.getUpdates(opts).then(() => {
|
||||||
|
return this._error(err);
|
||||||
|
}).catch(requestErr => {
|
||||||
|
/*
|
||||||
|
* We have been unable to handle this error.
|
||||||
|
* We have to log this to stderr to ensure devops
|
||||||
|
* understands that they may receive already-processed items
|
||||||
|
* on app restart.
|
||||||
|
* We simply can not rescue this situation, emit "error"
|
||||||
|
* event, with the hope that the application exits.
|
||||||
|
*/
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
const bugUrl = 'https://github.com/yagop/node-telegram-bot-api/issues/36#issuecomment-268532067';
|
||||||
|
console.error('error: Internal handling of The Offset Infinite Loop failed');
|
||||||
|
console.error(`error: Due to error '${requestErr}'`);
|
||||||
|
console.error('error: You may receive already-processed updates on app restart');
|
||||||
|
console.error(`error: Please see ${bugUrl} for more information`);
|
||||||
|
/* eslint-enable no-console */
|
||||||
|
return this.bot.emit('error', new errors.FatalError(err));
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
if (this._abort) {
|
if (this._abort) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user