mirror of
https://github.com/yagop/node-telegram-bot-api
synced 2025-08-29 05:17:41 +00:00
src: Add proper error handling (#283)
Feature: Please see `doc/usage.md` for more information on error-handling.
This commit is contained in:
parent
6f5dad6e5b
commit
eed7c1e4d0
@ -9,6 +9,7 @@ Added:
|
||||
|
||||
1. Add methods:
|
||||
* *TelegramBot#removeReplyListener()* (by @githugger)
|
||||
1. Add proper error handling (by @GochoMugo)
|
||||
1. Add health-check endpoint (by @mironov)
|
||||
* `options.webHook.healthEndpoint`
|
||||
1. Use *String#indexOf()*, instead of *RegExp#test()*, to
|
||||
|
60
doc/usage.md
60
doc/usage.md
@ -3,6 +3,7 @@
|
||||
1. [Events](#events)
|
||||
1. [WebHooks](#WebHooks)
|
||||
1. [Sending files](#sending-files)
|
||||
1. [Error handling](#error-handling)
|
||||
|
||||
|
||||
* * *
|
||||
@ -29,6 +30,8 @@
|
||||
1. `edited_channel_post`: Received a new version of a channel post that is known to the bot and was edited
|
||||
1. `edited_channel_post_text`
|
||||
1. `edited_channel_post_caption`
|
||||
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).
|
||||
|
||||
**Tip:** Its much better to listen a specific event rather than on
|
||||
`message` in order to stay safe from the content.
|
||||
@ -145,3 +148,60 @@ const bot = new TelegramBot(token, {
|
||||
filepath: false,
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
<a name="error-handling"></a>
|
||||
## Error handling
|
||||
|
||||
Every `Error` object we pass back has the properties:
|
||||
|
||||
* `code` (String):
|
||||
* value is `EFATAL` if error was fatal e.g. network error
|
||||
* value is `EPARSE` if response body could **not** be parsed
|
||||
* value is `ETELEGRAM` if error was returned from Telegram servers
|
||||
* `response` ([http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)):
|
||||
* available if `error.code` is **not** `EFATAL`
|
||||
* `response.body` (String|Object): Error response from Telegram
|
||||
* type is `String` if `error.code` is `EPARSE`
|
||||
* type is `Object` if `error.code` is `ETELEGRAM`
|
||||
|
||||
For example, sending message to a non-existent user:
|
||||
|
||||
```js
|
||||
bot.sendMessage(nonExistentUserId, 'text').catch(error => {
|
||||
console.log(error.code); // => 'ETELEGRAM'
|
||||
console.log(error.response.body); // => { ok: false, error_code: 400, description: 'Bad Request: chat not found' }
|
||||
});
|
||||
```
|
||||
|
||||
<a name="polling-errors"></a>
|
||||
#### Polling errors
|
||||
|
||||
An error may occur during polling. It is up to you to handle it
|
||||
as you see fit. You may decide to crash your bot after a maximum number
|
||||
of polling errors occurring. **It is all up to you.**
|
||||
|
||||
By default, the polling error is just logged to stderr, if you do
|
||||
**not** handle this event yourself.
|
||||
|
||||
Listen on the `'polling_error'` event. For example,
|
||||
|
||||
```js
|
||||
bot.on('polling_error', (error) => {
|
||||
console.log(error.code); // => 'EFATAL'
|
||||
});
|
||||
```
|
||||
|
||||
<a name="webhook-errors"></a>
|
||||
#### WebHook errors
|
||||
|
||||
Just like with [polling errors](#polling-errors), you decide on how to
|
||||
handle it. By default, the error is logged to stderr.
|
||||
|
||||
Listen on the `'webhook_error'` event. For example,
|
||||
|
||||
```js
|
||||
bot.on('webhook_error', (error) => {
|
||||
console.log(error.code); // => 'EPARSE'
|
||||
});
|
||||
```
|
||||
|
59
src/errors.js
Normal file
59
src/errors.js
Normal file
@ -0,0 +1,59 @@
|
||||
exports.BaseError = class BaseError extends Error {
|
||||
/**
|
||||
* @class BaseError
|
||||
* @constructor
|
||||
* @private
|
||||
* @param {String} code Error code
|
||||
* @param {String} message Error message
|
||||
*/
|
||||
constructor(code, message) {
|
||||
super(`${code}: ${message}`);
|
||||
this.code = code;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.FatalError = class FatalError extends exports.BaseError {
|
||||
/**
|
||||
* Fatal Error. Error code is `"EFATAL"`.
|
||||
* @class FatalError
|
||||
* @constructor
|
||||
* @param {String|Error} data Error object or message
|
||||
*/
|
||||
constructor(data) {
|
||||
const error = (typeof data === 'string') ? null : data;
|
||||
const message = error ? error.message : data;
|
||||
super('EFATAL', message);
|
||||
if (error) this.stack = error.stack;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.ParseError = class ParseError extends exports.BaseError {
|
||||
/**
|
||||
* Error during parsing. Error code is `"EPARSE"`.
|
||||
* @class ParseError
|
||||
* @constructor
|
||||
* @param {String} message Error message
|
||||
* @param {http.IncomingMessage} response Server response
|
||||
*/
|
||||
constructor(message, response) {
|
||||
super('EPARSE', message);
|
||||
this.response = response;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.TelegramError = class TelegramError extends exports.BaseError {
|
||||
/**
|
||||
* Error returned from Telegram. Error code is `"ETELEGRAM"`.
|
||||
* @class TelegramError
|
||||
* @constructor
|
||||
* @param {String} message Error message
|
||||
* @param {http.IncomingMessage} response Server response
|
||||
*/
|
||||
constructor(message, response) {
|
||||
super('ETELEGRAM', message);
|
||||
this.response = response;
|
||||
}
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
// shims
|
||||
require('array.prototype.findindex').shim(); // for Node.js v0.x
|
||||
|
||||
const errors = require('./errors');
|
||||
const TelegramBotWebHook = require('./telegramWebHook');
|
||||
const TelegramBotPolling = require('./telegramPolling');
|
||||
const debug = require('debug')('node-telegram-bot-api');
|
||||
@ -31,6 +32,10 @@ Promise.config({
|
||||
|
||||
class TelegramBot extends EventEmitter {
|
||||
|
||||
static get errors() {
|
||||
return errors;
|
||||
}
|
||||
|
||||
static get messageTypes() {
|
||||
return _messageTypes;
|
||||
}
|
||||
@ -136,7 +141,7 @@ class TelegramBot extends EventEmitter {
|
||||
*/
|
||||
_request(_path, options = {}) {
|
||||
if (!this.token) {
|
||||
throw new Error('Telegram Bot Token not provided!');
|
||||
return Promise.reject(new errors.FatalError('Telegram Bot Token not provided!'));
|
||||
}
|
||||
|
||||
if (this.options.request) {
|
||||
@ -158,30 +163,22 @@ class TelegramBot extends EventEmitter {
|
||||
debug('HTTP request: %j', options);
|
||||
return request(options)
|
||||
.then(resp => {
|
||||
if (resp.statusCode !== 200) {
|
||||
const error = new Error(`${resp.statusCode} ${resp.body}`);
|
||||
error.response = resp;
|
||||
throw error;
|
||||
}
|
||||
|
||||
let data;
|
||||
|
||||
try {
|
||||
data = JSON.parse(resp.body);
|
||||
data = resp.body = JSON.parse(resp.body);
|
||||
} catch (err) {
|
||||
const error = new Error(`Error parsing Telegram response: ${resp.body}`);
|
||||
error.response = resp;
|
||||
throw error;
|
||||
throw new errors.ParseError(`Error parsing Telegram response: ${resp.body}`, resp);
|
||||
}
|
||||
|
||||
if (data.ok) {
|
||||
return data.result;
|
||||
}
|
||||
|
||||
const error = new Error(`${data.error_code} ${data.description}`);
|
||||
error.response = resp;
|
||||
error.response.body = data;
|
||||
throw error;
|
||||
throw new errors.TelegramError(`${data.error_code} ${data.description}`, resp);
|
||||
}).catch(error => {
|
||||
// TODO: why can't we do `error instanceof errors.BaseError`?
|
||||
if (error.response) throw error;
|
||||
throw new errors.FatalError(error);
|
||||
});
|
||||
}
|
||||
|
||||
@ -215,7 +212,7 @@ class TelegramBot extends EventEmitter {
|
||||
} else if (Buffer.isBuffer(data)) {
|
||||
const filetype = fileType(data);
|
||||
if (!filetype) {
|
||||
throw new Error('Unsupported Buffer file type');
|
||||
throw new errors.FatalError('Unsupported Buffer file type');
|
||||
}
|
||||
formData = {};
|
||||
formData[type] = {
|
||||
@ -256,11 +253,11 @@ class TelegramBot extends EventEmitter {
|
||||
*/
|
||||
startPolling(options = {}) {
|
||||
if (this.hasOpenWebHook()) {
|
||||
return Promise.reject(new Error('Polling and WebHook are mutually exclusive'));
|
||||
return Promise.reject(new errors.FatalError('Polling and WebHook are mutually exclusive'));
|
||||
}
|
||||
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);
|
||||
}
|
||||
return this._polling.start(options);
|
||||
}
|
||||
@ -305,10 +302,10 @@ class TelegramBot extends EventEmitter {
|
||||
*/
|
||||
openWebHook() {
|
||||
if (this.isPolling()) {
|
||||
return Promise.reject(new Error('WebHook and Polling are mutually exclusive'));
|
||||
return Promise.reject(new errors.FatalError('WebHook and Polling are mutually exclusive'));
|
||||
}
|
||||
if (!this._webHook) {
|
||||
this._webHook = new TelegramBotWebHook(this.token, this.options.webHook, this.processUpdate.bind(this));
|
||||
this._webHook = new TelegramBotWebHook(this);
|
||||
}
|
||||
return this._webHook.open();
|
||||
}
|
||||
@ -385,14 +382,7 @@ class TelegramBot extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
return this._request('setWebHook', opts)
|
||||
.then(resp => {
|
||||
if (!resp) {
|
||||
throw new Error(resp);
|
||||
}
|
||||
|
||||
return resp;
|
||||
});
|
||||
return this._request('setWebHook', opts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,29 +5,14 @@ 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
|
||||
* @param {TelegramBot} bot
|
||||
* @see https://core.telegram.org/bots/api#getting-updates
|
||||
*/
|
||||
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 = (typeof options.timeout === 'number') ? options.timeout : 10;
|
||||
this.options.interval = (typeof options.interval === 'number') ? options.interval : 300;
|
||||
this.callback = callback;
|
||||
constructor(bot) {
|
||||
this.bot = bot;
|
||||
this.options = (typeof bot.options.polling === 'boolean') ? {} : bot.options.polling;
|
||||
this.options.timeout = (typeof this.options.timeout === 'number') ? this.options.timeout : 10;
|
||||
this.options.interval = (typeof this.options.interval === 'number') ? this.options.interval : 300;
|
||||
this._offset = 0;
|
||||
this._lastUpdate = 0;
|
||||
this._lastRequest = null;
|
||||
@ -102,13 +87,18 @@ class TelegramBotPolling {
|
||||
updates.forEach(update => {
|
||||
this._offset = update.update_id;
|
||||
debug('updated offset: %s', this._offset);
|
||||
this.callback(update);
|
||||
this.bot.processUpdate(update);
|
||||
});
|
||||
return null;
|
||||
})
|
||||
.catch(err => {
|
||||
debug('polling error: %s', err.message);
|
||||
throw err;
|
||||
if (this.bot.listeners('polling_error').length) {
|
||||
this.bot.emit('polling_error', err);
|
||||
} else {
|
||||
console.error(err); // eslint-disable-line no-console
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.finally(() => {
|
||||
if (this._abort) {
|
||||
@ -128,7 +118,7 @@ class TelegramBotPolling {
|
||||
* @private
|
||||
*/
|
||||
_unsetWebHook() {
|
||||
return this.request('setWebHook');
|
||||
return this.bot._request('setWebHook');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,7 +134,7 @@ class TelegramBotPolling {
|
||||
};
|
||||
debug('polling with options: %j', opts);
|
||||
|
||||
return this.request('getUpdates', opts)
|
||||
return this.bot._request('getUpdates', opts)
|
||||
.catch(err => {
|
||||
if (err.response && err.response.statusCode === ANOTHER_WEB_HOOK_USED) {
|
||||
return this._unsetWebHook();
|
||||
|
@ -1,3 +1,4 @@
|
||||
const errors = require('./errors');
|
||||
const debug = require('debug')('node-telegram-bot-api');
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
@ -9,27 +10,16 @@ const Promise = require('bluebird');
|
||||
class TelegramBotWebHook {
|
||||
/**
|
||||
* Sets up a webhook to receive updates
|
||||
*
|
||||
* @param {String} token Telegram API token
|
||||
* @param {Boolean|Object} options WebHook options
|
||||
* @param {String} [options.host=0.0.0.0] Host to bind to
|
||||
* @param {Number} [options.port=8443] Port to bind to
|
||||
* @param {String} [options.healthEndpoint=/healthz] An endpoint for health checks that always responds with 200 OK
|
||||
* @param {Function} callback Function for process a new update
|
||||
* @param {TelegramBot} bot
|
||||
* @see https://core.telegram.org/bots/api#getting-updates
|
||||
*/
|
||||
constructor(token, options, callback) {
|
||||
// define opts
|
||||
if (typeof options === 'boolean') {
|
||||
options = {}; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
this.token = token;
|
||||
this.options = options;
|
||||
this.options.host = options.host || '0.0.0.0';
|
||||
this.options.port = options.port || 8443;
|
||||
this.options.https = options.https || {};
|
||||
this.options.healthEndpoint = options.healthEndpoint || '/healthz';
|
||||
this.callback = callback;
|
||||
constructor(bot) {
|
||||
this.bot = bot;
|
||||
this.options = (typeof bot.options.webHook === 'boolean') ? {} : bot.options.webHook;
|
||||
this.options.host = this.options.host || '0.0.0.0';
|
||||
this.options.port = this.options.port || 8443;
|
||||
this.options.https = this.options.https || {};
|
||||
this.options.healthEndpoint = this.options.healthEndpoint || '/healthz';
|
||||
this._healthRegex = new RegExp(this.options.healthEndpoint);
|
||||
this._webServer = null;
|
||||
this._open = false;
|
||||
@ -100,31 +90,35 @@ class TelegramBotWebHook {
|
||||
return this._open;
|
||||
}
|
||||
|
||||
// used so that other funcs are not non-optimizable
|
||||
_safeParse(json) {
|
||||
try {
|
||||
return JSON.parse(json);
|
||||
} catch (err) {
|
||||
debug(err);
|
||||
return null;
|
||||
/**
|
||||
* Handle error thrown during processing of webhook request.
|
||||
* @private
|
||||
* @param {Error} error
|
||||
*/
|
||||
_error(error) {
|
||||
if (!this.bot.listeners('webhook_error').length) {
|
||||
return console.error(error); // eslint-disable-line no-console
|
||||
}
|
||||
return this.bot.emit('webhook_error', error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request body by passing it to 'callback'
|
||||
* @private
|
||||
*/
|
||||
_parseBody(err, body) {
|
||||
if (err) {
|
||||
return debug(err);
|
||||
_parseBody(error, body) {
|
||||
if (error) {
|
||||
return this._error(new errors.FatalError(error));
|
||||
}
|
||||
|
||||
const data = this._safeParse(body);
|
||||
if (data) {
|
||||
return this.callback(data);
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(body.toString());
|
||||
} catch (parseError) {
|
||||
return this._error(new errors.ParseError(parseError.message));
|
||||
}
|
||||
|
||||
return null;
|
||||
return this.bot.processUpdate(data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,7 +131,7 @@ class TelegramBotWebHook {
|
||||
debug('WebHook request URL: %s', req.url);
|
||||
debug('WebHook request headers: %j', req.headers);
|
||||
|
||||
if (req.url.indexOf(this.token) !== -1) {
|
||||
if (req.url.indexOf(this.bot.token) !== -1) {
|
||||
if (req.method !== 'POST') {
|
||||
debug('WebHook request isn\'t a POST');
|
||||
res.statusCode = 418; // I'm a teabot!
|
||||
|
@ -27,6 +27,7 @@ const pollingPort = portindex++;
|
||||
const webHookPort = portindex++;
|
||||
const pollingPort2 = portindex++;
|
||||
const webHookPort2 = portindex++;
|
||||
const badTgServerPort = portindex++;
|
||||
const staticUrl = `http://127.0.0.1:${staticPort}`;
|
||||
const key = `${__dirname}/../examples/key.pem`;
|
||||
const cert = `${__dirname}/../examples/crt.pem`;
|
||||
@ -39,6 +40,8 @@ before(function beforeAll() {
|
||||
return utils.startMockServer(pollingPort)
|
||||
.then(() => {
|
||||
return utils.startMockServer(pollingPort2);
|
||||
}).then(() => {
|
||||
return utils.startMockServer(badTgServerPort, { bad: true });
|
||||
});
|
||||
});
|
||||
|
||||
@ -125,17 +128,33 @@ describe('TelegramBot', function telegramSuite() {
|
||||
return done();
|
||||
});
|
||||
});
|
||||
it('(polling) emits "polling_error" if error occurs during polling', function test(done) {
|
||||
const myBot = new TelegramBot(12345, { polling: true });
|
||||
myBot.once('polling_error', (error) => {
|
||||
assert.ok(error);
|
||||
assert.equal(error.code, 'ETELEGRAM');
|
||||
return myBot.stopPolling().then(() => { done(); }).catch(done);
|
||||
});
|
||||
});
|
||||
it('(webhook) emits "message" on receiving message', function test(done) {
|
||||
botWebHook.once('message', () => {
|
||||
return done();
|
||||
});
|
||||
utils.sendWebHookMessage(webHookPort2, TOKEN);
|
||||
});
|
||||
it('(webhook) emits "webhook_error" if could not parse webhook request body', function test(done) {
|
||||
botWebHook.once('webhook_error', (error) => {
|
||||
assert.ok(error);
|
||||
assert.equal(error.code, 'EPARSE');
|
||||
return done();
|
||||
});
|
||||
utils.sendWebHookMessage(webHookPort2, TOKEN, { update: 'unparseable!', json: false });
|
||||
});
|
||||
});
|
||||
|
||||
describe('WebHook', function webHookSuite() {
|
||||
it('returns 200 OK for health endpoint', function test(done) {
|
||||
utils.sendWebHookRequest(webHookPort2, '/healthz', { json: false }).then(resp => {
|
||||
utils.sendWebHookRequest(webHookPort2, '/healthz').then(resp => {
|
||||
assert.equal(resp, 'OK');
|
||||
return done();
|
||||
});
|
||||
@ -186,6 +205,58 @@ describe('TelegramBot', function telegramSuite() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('errors', function errorsSuite() {
|
||||
const botParse = new TelegramBot('useless-token', {
|
||||
baseApiUrl: `http://localhost:${badTgServerPort}`,
|
||||
});
|
||||
it('FatalError is thrown if token is missing', function test() {
|
||||
const myBot = new TelegramBot(null);
|
||||
return myBot.sendMessage(USERID, 'text').catch(error => {
|
||||
// FIX: assert.ok(error instanceof TelegramBot.errors.FatalError);
|
||||
assert.equal(error.code, 'EFATAL');
|
||||
assert.ok(error.message.indexOf('not provided') > -1);
|
||||
});
|
||||
});
|
||||
it('FatalError is thrown if file-type of Buffer could not be determined', function test() {
|
||||
let buffer;
|
||||
try {
|
||||
buffer = Buffer.from('12345');
|
||||
} catch (ex) {
|
||||
buffer = new Buffer('12345');
|
||||
}
|
||||
return bot.sendPhoto(USERID, buffer).catch(error => {
|
||||
// FIX: assert.ok(error instanceof TelegramBot.errors.FatalError);
|
||||
assert.equal(error.code, 'EFATAL');
|
||||
assert.ok(error.message.indexOf('Unsupported') > -1);
|
||||
});
|
||||
});
|
||||
it('FatalError is thrown on network error', function test() {
|
||||
const myBot = new TelegramBot('useless-token', {
|
||||
baseApiUrl: 'http://localhost:23', // are we sure this port is not bound to?
|
||||
});
|
||||
return myBot.getMe().catch(error => {
|
||||
// FIX: assert.ok(error instanceof TelegramBot.errors.FatalError);
|
||||
assert.equal(error.code, 'EFATAL');
|
||||
});
|
||||
});
|
||||
it('ParseError is thrown if response body could not be parsed', function test() {
|
||||
botParse.sendMessage(USERID, 'text').catch(error => {
|
||||
// FIX: assert.ok(error instanceof TelegramBot.errors.ParseError);
|
||||
assert.equal(error.code, 'EPARSE');
|
||||
assert.ok(typeof error.response === 'object');
|
||||
assert.ok(typeof error.response.body === 'string');
|
||||
});
|
||||
});
|
||||
it('TelegramError is thrown if error is from Telegram', function test() {
|
||||
return bot.sendMessage('404', 'text').catch(error => {
|
||||
// FIX: assert.ok(error instanceof TelegramBot.errors.TelegramError);
|
||||
assert.equal(error.code, 'ETELEGRAM');
|
||||
assert.ok(typeof error.response === 'object');
|
||||
assert.ok(typeof error.response.body === 'object');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#startPolling', function initPollingSuite() {
|
||||
it('initiates polling', function test() {
|
||||
return testbot.startPolling().then(() => {
|
||||
@ -195,6 +266,8 @@ describe('TelegramBot', function telegramSuite() {
|
||||
it('returns error if using webhook', function test() {
|
||||
return botWebHook.startPolling().catch((err) => {
|
||||
// TODO: check for error in a better way
|
||||
// FIX: assert.ok(err instanceof TelegramBot.errors.FatalError);
|
||||
assert.equal(err.code, 'EFATAL');
|
||||
assert.ok(err.message.indexOf('mutually exclusive') !== -1);
|
||||
});
|
||||
});
|
||||
@ -235,6 +308,8 @@ describe('TelegramBot', function telegramSuite() {
|
||||
it('returns error if using polling', function test() {
|
||||
return botPolling.openWebHook().catch((err) => {
|
||||
// TODO: check for error in a better way
|
||||
// FIX: assert.ok(err instanceof TelegramBot.errors.FatalError);
|
||||
assert.equal(err.code, 'EFATAL');
|
||||
assert.ok(err.message.indexOf('mutually exclusive') !== -1);
|
||||
});
|
||||
});
|
||||
@ -1020,7 +1095,7 @@ describe('TelegramBot', function telegramSuite() {
|
||||
const photo = `${__dirname}/data/photo.gif`;
|
||||
return tgbot.sendPhoto(USERID, photo).catch(err => {
|
||||
// TODO: check for error in a better way
|
||||
assert.ok(err.response.body.indexOf('Bad Request') !== -1);
|
||||
assert.ok(err.response.body.description.indexOf('Bad Request') !== -1);
|
||||
});
|
||||
});
|
||||
it('should allow stream.path that can not be parsed', function test() {
|
||||
|
@ -36,6 +36,7 @@ exports = module.exports = {
|
||||
* @param {String} path
|
||||
* @param {Object} [options]
|
||||
* @param {String} [options.method=POST] Method to use
|
||||
* @param {Object} [options.update] Update object to send.
|
||||
* @param {Object} [options.message] Message to send. Default to a generic text message
|
||||
* @param {Boolean} [options.https=false] Use https
|
||||
* @return {Promise}
|
||||
@ -47,6 +48,7 @@ exports = module.exports = {
|
||||
* @param {String} token
|
||||
* @param {Object} [options]
|
||||
* @param {String} [options.method=POST] Method to use
|
||||
* @param {Object} [options.update] Update object to send.
|
||||
* @param {Object} [options.message] Message to send. Default to a generic text message
|
||||
* @param {Boolean} [options.https=false] Use https
|
||||
* @return {Promise}
|
||||
@ -55,6 +57,9 @@ exports = module.exports = {
|
||||
/**
|
||||
* Start a mock server at the specified port.
|
||||
* @param {Number} port
|
||||
* @param {Object} [options]
|
||||
* @param {Boolean} [options.bad=false] Bad Mock Server; responding with
|
||||
* unparseable messages
|
||||
* @return {Promise}
|
||||
*/
|
||||
startMockServer,
|
||||
@ -76,10 +81,13 @@ const statics = require('node-static');
|
||||
const servers = {};
|
||||
|
||||
|
||||
function startMockServer(port) {
|
||||
function startMockServer(port, options = {}) {
|
||||
assert.ok(port);
|
||||
const server = http.Server((req, res) => {
|
||||
servers[port].polling = true;
|
||||
if (options.bad) {
|
||||
return res.end('can not be parsed with JSON.parse()');
|
||||
}
|
||||
return res.end(JSON.stringify({
|
||||
ok: true,
|
||||
result: [{
|
||||
@ -153,11 +161,11 @@ function sendWebHookRequest(port, path, options = {}) {
|
||||
return request({
|
||||
url,
|
||||
method: options.method || 'POST',
|
||||
body: {
|
||||
body: options.update || {
|
||||
update_id: 1,
|
||||
message: options.message || { text: 'test' }
|
||||
},
|
||||
json: options.json || true,
|
||||
json: (typeof options.json === 'undefined') ? true : options.json,
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user