2
0
mirror of https://github.com/yagop/node-telegram-bot-api synced 2025-08-31 14:25:57 +00:00

[webhook,polling] Improve starting, stopping of webhook, polling

Feature:

  The different mechanisms of fetching updates, i.e. polling
  and webhook, have had their implementations improved:

  * the TelegramBot instance needs to create the polling and
    webhook instances once, and when necessary
  * returning promises from TelegramBot#openWebHook() and
    TelegramBot#startPolling() allows more precise control

  Also,

  * TelegramBot#initPolling() is being deprecated in favor of
    TelegramBot#startPolling() to ensure consistency (as the
    opposite action of TelegramBot#stopPolling())
This commit is contained in:
GochoMugo
2017-01-09 15:57:34 +03:00
parent 4735518116
commit 97c8130d93
5 changed files with 159 additions and 61 deletions

View File

@@ -71,10 +71,11 @@ TelegramBot
* [TelegramBot](#TelegramBot)
* [new TelegramBot(token, [options])](#new_TelegramBot_new)
* [.initPolling()](#TelegramBot+initPolling)
* [.startPolling([options])](#TelegramBot+startPolling) ⇒ <code>Promise</code>
* ~~[.initPolling([options])](#TelegramBot+initPolling) ⇒ <code>Promise</code>~~
* [.stopPolling()](#TelegramBot+stopPolling) ⇒ <code>Promise</code>
* [.isPolling()](#TelegramBot+isPolling) ⇒ <code>Boolean</code>
* [.openWebHook()](#TelegramBot+openWebHook)
* [.openWebHook()](#TelegramBot+openWebHook)<code>Promise</code>
* [.closeWebHook()](#TelegramBot+closeWebHook) ⇒ <code>Promise</code>
* [.hasOpenWebHook()](#TelegramBot+hasOpenWebHook) ⇒ <code>Boolean</code>
* [.getMe()](#TelegramBot+getMe) ⇒ <code>Promise</code>
@@ -144,19 +145,39 @@ 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.baseApiUrl] | <code>String</code> | <code>https://api.telegram.org</code> | API Base URl; useful for proxying and testing |
<a name="TelegramBot+initPolling"></a>
<a name="TelegramBot+startPolling"></a>
### telegramBot.initPolling()
Start polling
### telegramBot.startPolling([options]) ⇒ <code>Promise</code>
Start polling.
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| [options] | <code>Object</code> | | |
| [options.restart] | <code>Boolean</code> | <code>true</code> | Consecutive calls to this method causes polling to be restarted |
<a name="TelegramBot+initPolling"></a>
### ~~telegramBot.initPolling([options]) ⇒ <code>Promise</code>~~
***Deprecated***
Alias of `TelegramBot#startPolling()`. This is **deprecated**.
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
| Param | Type |
| --- | --- |
| [options] | <code>Object</code> |
<a name="TelegramBot+stopPolling"></a>
### telegramBot.stopPolling() ⇒ <code>Promise</code>
Stops polling after the last polling request resolves
Stops polling after the last polling request resolves.
Multiple invocations do nothing if polling is already stopped.
Returning the promise of the last polling request is **deprecated**.
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
**Returns**: <code>Promise</code> - promise Promise, of last polling request
<a name="TelegramBot+isPolling"></a>
### telegramBot.isPolling() ⇒ <code>Boolean</code>
@@ -165,14 +186,16 @@ Return true if polling. Otherwise, false.
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
<a name="TelegramBot+openWebHook"></a>
### telegramBot.openWebHook()
Open webhook
### telegramBot.openWebHook() ⇒ <code>Promise</code>
Open webhook.
Multiple invocations do nothing if webhook is already open.
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
<a name="TelegramBot+closeWebHook"></a>
### telegramBot.closeWebHook() ⇒ <code>Promise</code>
Close webhook after closing all current connections
Close webhook after closing all current connections.
Multiple invocations do nothing if webhook is already closed.
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
**Returns**: <code>Promise</code> - promise

View File

@@ -72,11 +72,13 @@ class TelegramBot extends EventEmitter {
this.options.baseApiUrl = options.baseApiUrl || 'https://api.telegram.org';
this._textRegexpCallbacks = [];
this._onReplyToMessages = [];
this._polling = null;
this._webHook = null;
if (options.polling) {
const autoStart = options.polling.autoStart;
if (typeof autoStart === 'undefined' || autoStart === true) {
this.initPolling();
this.startPolling();
}
}
@@ -223,29 +225,41 @@ class TelegramBot extends EventEmitter {
}
/**
* Start polling
* Start polling.
* @param {Object} [options]
* @param {Boolean} [options.restart=true] Consecutive calls to this method causes polling to be restarted
* @return {Promise}
*/
initPolling() {
if (this._polling) {
this._polling.stopPolling({
cancel: true,
reason: 'Polling restart',
});
startPolling(options = {}) {
options.restart = typeof options.restart === 'undefined' ? true : options.restart;
if (!this._polling) {
this._polling = new TelegramBotPolling(this._request.bind(this), this.options.polling, this.processUpdate.bind(this));
}
this._polling = new TelegramBotPolling(this._request.bind(this), this.options.polling, this.processUpdate.bind(this));
return this._polling.start(options);
}
/**
* Stops polling after the last polling request resolves
* @return {Promise} promise Promise, of last polling request
* Alias of `TelegramBot#startPolling()`. This is **deprecated**.
* @param {Object} [options]
* @return {Promise}
* @deprecated
*/
initPolling() {
deprecate('TelegramBot#initPolling() is deprecated');
return this.startPolling();
}
/**
* Stops polling after the last polling request resolves.
* Multiple invocations do nothing if polling is already stopped.
* Returning the promise of the last polling request is **deprecated**.
* @return {Promise}
*/
stopPolling() {
if (!this._polling) {
return Promise.resolve();
}
const polling = this._polling;
delete this._polling;
return polling.stopPolling();
return this._polling.stop();
}
/**
@@ -253,30 +267,31 @@ class TelegramBot extends EventEmitter {
* @return {Boolean}
*/
isPolling() {
return !!this._polling;
return this._polling ? this._polling.isPolling() : false;
}
/**
* Open webhook
* Open webhook.
* Multiple invocations do nothing if webhook is already open.
* @return {Promise}
*/
openWebHook() {
if (this._webHook) {
return;
if (!this._webHook) {
this._webHook = new TelegramBotWebHook(this.token, this.options.webHook, this.processUpdate.bind(this));
}
this._webHook = new TelegramBotWebHook(this.token, this.options.webHook, this.processUpdate.bind(this));
return this._webHook.open();
}
/**
* Close webhook after closing all current connections
* Close webhook after closing all current connections.
* Multiple invocations do nothing if webhook is already closed.
* @return {Promise} promise
*/
closeWebHook() {
if (!this._webHook) {
return Promise.resolve();
}
const webHook = this._webHook;
delete this._webHook;
return webHook.close();
return this._webHook.close();
}
/**
@@ -285,7 +300,7 @@ class TelegramBot extends EventEmitter {
* @return {Boolean}
*/
hasOpenWebHook() {
return !!this._webHook;
return this._webHook ? this._webHook.isOpen() : false;
}
/**

View File

@@ -33,7 +33,27 @@ class TelegramBotPolling {
this._lastRequest = null;
this._abort = false;
this._pollingTimeout = null;
this._polling();
}
/**
* Start polling
* @param {Object} [options]
* @param {Object} [options.restart]
* @return {Promise}
*/
start(options = {}) {
if (this._lastRequest) {
if (!options.restart) {
return Promise.resolve();
}
return this.stop({
cancel: true,
reason: 'Polling restart',
}).then(() => {
return this._polling();
});
}
return this._polling();
}
/**
@@ -41,20 +61,36 @@ class TelegramBotPolling {
* @param {Object} [options]
* @param {Boolean} [options.cancel] Cancel current request
* @param {String} [options.reason] Reason for stopping polling
* @return {Promise}
*/
stopPolling(options = {}) {
this._abort = true;
stop(options = {}) {
if (!this._lastRequest) {
return Promise.resolve();
}
const lastRequest = this._lastRequest;
this._lastRequest = null;
clearTimeout(this._pollingTimeout);
if (options.cancel) {
const reason = options.reason || 'Polling stop';
return this._lastRequest.cancel(reason);
lastRequest.cancel(reason);
return Promise.resolve();
}
// wait until the last request is fulfilled
return this._lastRequest;
this._abort = true;
return lastRequest.finally(() => {
this._abort = false;
});
}
/**
* Return `true` if is polling. Otherwise, `false`.
*/
isPolling() {
return !!this._lastRequest;
}
/**
* Invokes polling (with recursion!)
* @return {Promise} promise of the current request
* @private
*/
_polling() {
@@ -81,6 +117,7 @@ class TelegramBotPolling {
this._pollingTimeout = setTimeout(() => this._polling(), this.options.interval);
}
});
return this._lastRequest;
}
/**

View File

@@ -47,12 +47,47 @@ class TelegramBotWebHook {
debug('HTTP WebHook enabled');
this._webServer = http.createServer(this._requestListener);
}
}
this._webServer.listen(this.options.port, this.options.host, () => {
debug('WebHook listening on port %s', this.options.port);
/**
* Open WebHook by listening on the port
* @return {Promise}
*/
open() {
if (this._webServer.listening) {
return Promise.resolve();
}
return new Promise(resolve => {
this._webServer.listen(this.options.port, this.options.host, () => {
debug('WebHook listening on port %s', this.options.port);
return resolve();
});
});
}
/**
* Close the webHook
* @return {Promise}
*/
close() {
if (!this._webServer.listening) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
this._webServer.close(error => {
if (error) return reject(error);
return resolve();
});
});
}
/**
* Return `true` if server is listening. Otherwise, `false`.
*/
isOpen() {
return this._webServer.listening;
}
// used so that other funcs are not non-optimizable
_safeParse(json) {
try {
@@ -106,20 +141,6 @@ class TelegramBotWebHook {
res.end();
}
}
/**
* Close the webHook
* @return {Promise}
*/
close() {
const self = this;
return new Promise(function closePromise(resolve, reject) {
self._webServer.close(function closeCb(error) {
if (error) return reject(error);
return resolve();
});
});
}
}
module.exports = TelegramBotWebHook;

View File

@@ -178,10 +178,11 @@ describe('TelegramBot', function telegramSuite() {
});
});
describe('#initPolling', function initPollingSuite() {
describe('#startPolling', function initPollingSuite() {
it('initiates polling', function test() {
testbot.initPolling();
return utils.isPollingMockServer(pollingPort);
return testbot.startPolling().then(() => {
return utils.isPollingMockServer(pollingPort);
});
});
});
@@ -213,8 +214,9 @@ describe('TelegramBot', function telegramSuite() {
describe('#openWebHook', function openWebHookSuite() {
it('opens webhook', function test() {
testbot.openWebHook();
return utils.hasOpenWebHook(webHookPort);
return testbot.openWebHook().then(() => {
return utils.hasOpenWebHook(webHookPort);
});
});
});