diff --git a/README.md b/README.md index 3432e53..0dbd431 100644 --- a/README.md +++ b/README.md @@ -71,10 +71,11 @@ TelegramBot * [TelegramBot](#TelegramBot) * [new TelegramBot(token, [options])](#new_TelegramBot_new) - * [.initPolling()](#TelegramBot+initPolling) + * [.startPolling([options])](#TelegramBot+startPolling) ⇒ Promise + * ~~[.initPolling([options])](#TelegramBot+initPolling) ⇒ Promise~~ * [.stopPolling()](#TelegramBot+stopPolling) ⇒ Promise * [.isPolling()](#TelegramBot+isPolling) ⇒ Boolean - * [.openWebHook()](#TelegramBot+openWebHook) + * [.openWebHook()](#TelegramBot+openWebHook) ⇒ Promise * [.closeWebHook()](#TelegramBot+closeWebHook) ⇒ Promise * [.hasOpenWebHook()](#TelegramBot+hasOpenWebHook) ⇒ Boolean * [.getMe()](#TelegramBot+getMe) ⇒ Promise @@ -144,19 +145,39 @@ Emits `message` when a message arrives. | [options.request] | Object | | Options which will be added for all requests to telegram api. See https://github.com/request/request#requestoptions-callback for more information. | | [options.baseApiUrl] | String | https://api.telegram.org | API Base URl; useful for proxying and testing | - + -### telegramBot.initPolling() -Start polling +### telegramBot.startPolling([options]) ⇒ Promise +Start polling. **Kind**: instance method of [TelegramBot](#TelegramBot) + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [options] | Object | | | +| [options.restart] | Boolean | true | Consecutive calls to this method causes polling to be restarted | + + + +### ~~telegramBot.initPolling([options]) ⇒ Promise~~ +***Deprecated*** + +Alias of `TelegramBot#startPolling()`. This is **deprecated**. + +**Kind**: instance method of [TelegramBot](#TelegramBot) + +| Param | Type | +| --- | --- | +| [options] | Object | + ### telegramBot.stopPolling() ⇒ Promise -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 [TelegramBot](#TelegramBot) -**Returns**: Promise - promise Promise, of last polling request ### telegramBot.isPolling() ⇒ Boolean @@ -165,14 +186,16 @@ Return true if polling. Otherwise, false. **Kind**: instance method of [TelegramBot](#TelegramBot) -### telegramBot.openWebHook() -Open webhook +### telegramBot.openWebHook() ⇒ Promise +Open webhook. +Multiple invocations do nothing if webhook is already open. **Kind**: instance method of [TelegramBot](#TelegramBot) ### telegramBot.closeWebHook() ⇒ Promise -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 [TelegramBot](#TelegramBot) **Returns**: Promise - promise diff --git a/src/telegram.js b/src/telegram.js index 36851de..326b7c9 100644 --- a/src/telegram.js +++ b/src/telegram.js @@ -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; } /** diff --git a/src/telegramPolling.js b/src/telegramPolling.js index 70b2516..b2e3464 100644 --- a/src/telegramPolling.js +++ b/src/telegramPolling.js @@ -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; } /** diff --git a/src/telegramWebHook.js b/src/telegramWebHook.js index e99d3e9..5db9fcc 100644 --- a/src/telegramWebHook.js +++ b/src/telegramWebHook.js @@ -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; diff --git a/test/telegram.js b/test/telegram.js index d1731e4..b273365 100644 --- a/test/telegram.js +++ b/test/telegram.js @@ -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); + }); }); });