2
0
mirror of https://github.com/yagop/node-telegram-bot-api synced 2025-08-22 18:07:16 +00:00

refactor: rewrite to babel, es6 & eslint

This commit is contained in:
AVVS 2016-03-17 02:44:34 +03:00
parent b9649c00bb
commit 83e42201ee
14 changed files with 1062 additions and 1019 deletions

11
.babelrc Normal file
View File

@ -0,0 +1,11 @@
{
"plugins": [
"transform-es2015-spread",
"transform-es2015-destructuring",
"transform-strict-mode",
"transform-es2015-parameters",
"transform-es2015-shorthand-properties",
"transform-object-rest-spread",
"transform-class-properties"
]
}

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
bin
*.md

18
.eslintrc Normal file
View File

@ -0,0 +1,18 @@
{
"extends": "airbnb/base",
"parser": "babel-eslint",
"rules": {
"new-cap": 0,
"prefer-arrow-callback": 0,
"no-param-reassign": [2,{"props":false}],
"max-len": [2, 150],
"arrow-body-style": 0,
"comma-dangle": 0
},
"plugins": [
"mocha"
],
"env": {
"mocha": true
}
}

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ npm-debug.log
.package.json .package.json
output.md output.md
output/ output/
lib/

View File

@ -1,11 +0,0 @@
{
"curly" : true,
"eqeqeq" : true,
"indent" : 2,
"latedef" : true,
"newcap" : true,
"quotmark": "single",
"strict" : true,
"undef" : true,
"node" : true
}

View File

@ -1,8 +1,7 @@
language: node_js language: node_js
node_js: node_js:
- "stable" - "5"
- "0.12" - "4"
- "0.10"
after_success: after_success:
- npm run test-cov - npm run test-cov
cache: cache:

View File

@ -2,7 +2,7 @@
"name": "node-telegram-bot-api", "name": "node-telegram-bot-api",
"version": "0.21.1", "version": "0.21.1",
"description": "Telegram Bot API", "description": "Telegram Bot API",
"main": "index.js", "main": "./lib/telegram.js",
"directories": { "directories": {
"example": "examples", "example": "examples",
"test": "test" "test": "test"
@ -14,29 +14,46 @@
"bot" "bot"
], ],
"scripts": { "scripts": {
"prepublish": "./node_modules/.bin/babel -d ./lib src",
"test": "./node_modules/.bin/mocha test/index.js", "test": "./node_modules/.bin/mocha test/index.js",
"test-cov": "./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage", "test-cov": "./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage",
"gen-doc": "./node_modules/.bin/jsdoc2md --src src/telegram.js -t README.hbs > README.md", "gen-doc": "./node_modules/.bin/jsdoc2md --src src/telegram.js -t README.hbs > README.md",
"jshint": "./node_modules/.bin/jshint src test" "eslint": "./node_modules/.bin/eslint ./src"
}, },
"author": "Yago Pérez <yagoperezs@gmail.com>", "author": "Yago Pérez <yagoperezs@gmail.com>",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"bluebird": "^2.10.2", "bl": "^1.1.2",
"bluebird": "^3.3.4",
"debug": "^2.2.0", "debug": "^2.2.0",
"eventemitter3": "^1.2.0",
"file-type": "^3.8.0", "file-type": "^3.8.0",
"mime": "^1.3.4", "mime": "^1.3.4",
"request": "^2.69.0" "pump": "^1.0.1",
"request": "^2.69.0",
"request-promise": "^2.0.1"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.6.5",
"babel-eslint": "^5.0.0",
"babel-plugin-transform-class-properties": "^6.6.0",
"babel-plugin-transform-es2015-destructuring": "^6.6.5",
"babel-plugin-transform-es2015-parameters": "^6.7.0",
"babel-plugin-transform-es2015-shorthand-properties": "^6.5.0",
"babel-plugin-transform-es2015-spread": "^6.6.5",
"babel-plugin-transform-object-rest-spread": "^6.6.5",
"babel-plugin-transform-strict-mode": "^6.6.5",
"babel-register": "^6.7.2",
"contributor": "^0.1.25", "contributor": "^0.1.25",
"coveralls": "^2.11.8", "coveralls": "^2.11.8",
"eslint": "^2.4.0",
"eslint-config-airbnb": "^6.1.0",
"eslint-plugin-mocha": "^2.0.0",
"is": "^3.1.0",
"istanbul": "^0.4.2", "istanbul": "^0.4.2",
"jsdoc-to-markdown": "^1.3.3", "jsdoc-to-markdown": "^1.3.3",
"jshint": "^2.9.1",
"mocha": "^2.4.5", "mocha": "^2.4.5",
"mocha-lcov-reporter": "^1.2.0", "mocha-lcov-reporter": "^1.2.0"
"should": "^8.2.2"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -1,21 +1,18 @@
'use strict'; const TelegramBotWebHook = require('./telegramWebHook');
const TelegramBotPolling = require('./telegramPolling');
var TelegramBotWebHook = require('./telegramWebHook'); const debug = require('debug')('node-telegram-bot-api');
var TelegramBotPolling = require('./telegramPolling'); const EventEmitter = require('eventemitter3');
var debug = require('debug')('node-telegram-bot-api'); const fileType = require('file-type');
var EventEmitter = require('events').EventEmitter; const Promise = require('bluebird');
var fileType = require('file-type'); const request = require('request-promise');
var Promise = require('bluebird'); const streamedRequest = require('request');
var request = require('request'); const qs = require('querystring');
var qs = require('querystring'); const stream = require('stream');
var stream = require('stream'); const mime = require('mime');
var util = require('util'); const path = require('path');
var mime = require('mime'); const URL = require('url');
var path = require('path'); const fs = require('fs');
var URL = require('url'); const pump = require('pump');
var fs = require('fs');
var requestPromise = Promise.promisify(request);
/** /**
* Both request method to obtain messages are implemented. To use standard polling, set `polling: true` * Both request method to obtain messages are implemented. To use standard polling, set `polling: true`
@ -34,20 +31,22 @@ var requestPromise = Promise.promisify(request);
* @param {String} [options.webHook.cert] PEM certificate (public) to webHook server. * @param {String} [options.webHook.cert] PEM certificate (public) to webHook server.
* @see https://core.telegram.org/bots/api * @see https://core.telegram.org/bots/api
*/ */
var TelegramBot = function (token, options) { class TelegramBot extends EventEmitter {
options = options || {};
this.options = options; // Telegram message events
this.token = token; static messageTypes = [
this.messageTypes = [
'text', 'audio', 'document', 'photo', 'sticker', 'video', 'voice', 'contact', 'text', 'audio', 'document', 'photo', 'sticker', 'video', 'voice', 'contact',
'location', 'new_chat_participant', 'left_chat_participant', 'new_chat_title', 'location', 'new_chat_participant', 'left_chat_participant', 'new_chat_title',
'new_chat_photo', 'delete_chat_photo', 'group_chat_created' 'new_chat_photo', 'delete_chat_photo', 'group_chat_created'
]; // Telegram message events ];
constructor(token, options = {}) {
super();
this.options = options;
this.token = token;
this.textRegexpCallbacks = []; this.textRegexpCallbacks = [];
this.onReplyToMessages = []; this.onReplyToMessages = [];
this.processUpdate = this._processUpdate.bind(this);
if (options.polling) { if (options.polling) {
this.initPolling(); this.initPolling();
} }
@ -55,39 +54,37 @@ var TelegramBot = function (token, options) {
if (options.webHook) { if (options.webHook) {
this._WebHook = new TelegramBotWebHook(token, options.webHook, this.processUpdate); this._WebHook = new TelegramBotWebHook(token, options.webHook, this.processUpdate);
} }
}; }
util.inherits(TelegramBot, EventEmitter); initPolling() {
TelegramBot.prototype.initPolling = function() {
if (this._polling) { if (this._polling) {
this._polling.abort = true; this._polling.abort = true;
this._polling.lastRequest.cancel('Polling restart'); this._polling.lastRequest.cancel('Polling restart');
} }
this._polling = new TelegramBotPolling(this.token, this.options.polling, this.processUpdate); this._polling = new TelegramBotPolling(this.token, this.options.polling, this.processUpdate);
}; }
TelegramBot.prototype._processUpdate = function (update) { processUpdate = (update) => {
debug('Process Update %j', update); debug('Process Update %j', update);
var message = update.message; const message = update.message;
var inline_query = update.inline_query; const inlineQuery = update.inline_query;
var chosen_inline_result = update.chosen_inline_result; const chosenInlineResult = update.chosen_inline_result;
if (message) { if (message) {
debug('Process Update message %j', message); debug('Process Update message %j', message);
this.emit('message', message); this.emit('message', message);
var processMessageType = function (messageType) { const processMessageType = messageType => {
if (message[messageType]) { if (message[messageType]) {
debug('Emtting %s: %j', messageType, message); debug('Emtting %s: %j', messageType, message);
this.emit(messageType, message); this.emit(messageType, message);
} }
}; };
this.messageTypes.forEach(processMessageType.bind(this)); TelegramBot.messageTypes.forEach(processMessageType);
if (message.text) { if (message.text) {
debug('Text message'); debug('Text message');
this.textRegexpCallbacks.forEach(function (reg) { this.textRegexpCallbacks.forEach(reg => {
debug('Matching %s whith', message.text, reg.regexp); debug('Matching %s whith', message.text, reg.regexp);
var result = reg.regexp.exec(message.text); const result = reg.regexp.exec(message.text);
if (result) { if (result) {
debug('Matches', reg.regexp); debug('Matches', reg.regexp);
reg.callback(message, result); reg.callback(message, result);
@ -96,7 +93,7 @@ TelegramBot.prototype._processUpdate = function (update) {
} }
if (message.reply_to_message) { if (message.reply_to_message) {
// Only callbacks waiting for this message // Only callbacks waiting for this message
this.onReplyToMessages.forEach(function (reply) { this.onReplyToMessages.forEach(reply => {
// Message from the same chat // Message from the same chat
if (reply.chatId === message.chat.id) { if (reply.chatId === message.chat.id) {
// Responding to that message // Responding to that message
@ -107,102 +104,109 @@ TelegramBot.prototype._processUpdate = function (update) {
} }
}); });
} }
} else if (inline_query) { } else if (inlineQuery) {
debug('Process Update inline_query %j', inline_query); debug('Process Update inline_query %j', inlineQuery);
this.emit('inline_query', inline_query); this.emit('inline_query', inlineQuery);
} else if (chosen_inline_result) { } else if (chosenInlineResult) {
debug('Process Update chosen_inline_result %j', chosen_inline_result); debug('Process Update chosen_inline_result %j', chosenInlineResult);
this.emit('chosen_inline_result', chosen_inline_result); this.emit('chosen_inline_result', chosenInlineResult);
}
} }
};
TelegramBot.prototype._request = function (path, options) { // used so that other funcs are not non-optimizable
_safeParse(json) {
try {
return JSON.parse(json);
} catch (err) {
throw new Error(`Error parsing Telegram response: ${String(json)}`);
}
}
// request-promise
_request(_path, options = {}) {
if (!this.token) { if (!this.token) {
throw new Error('Telegram Bot Token not provided!'); throw new Error('Telegram Bot Token not provided!');
} }
options = options || {};
if (options.form) { if (options.form) {
var replyMarkup = options.form.reply_markup; const replyMarkup = options.form.reply_markup;
if (replyMarkup && typeof replyMarkup !== 'string') { if (replyMarkup && typeof replyMarkup !== 'string') {
// reply_markup must be passed as JSON stringified to Telegram // reply_markup must be passed as JSON stringified to Telegram
options.form.reply_markup = JSON.stringify(replyMarkup); options.form.reply_markup = JSON.stringify(replyMarkup);
} }
} }
options.url = this._buildURL(path); options.url = this._buildURL(_path);
options.simple = false;
options.resolveWithFullResponse = true;
debug('HTTP request: %j', options); debug('HTTP request: %j', options);
return requestPromise(options) return request(options)
.then(function (resp) { .then(resp => {
if (resp[0].statusCode !== 200) { if (resp.statusCode !== 200) {
throw new Error(resp[0].statusCode+' '+resp[0].body); throw new Error(`${resp.statusCode} ${resp.body}`);
}
var data;
try {
data = JSON.parse(resp[0].body);
} catch (err) {
throw new Error('Error parsing Telegram response: %s', resp[0].body);
} }
const data = this._safeParse(resp.body);
if (data.ok) { if (data.ok) {
return data.result; return data.result;
} else {
throw new Error(data.error_code+' '+data.description);
} }
});
};
/** throw new Error(`${data.error_code} ${data.description}`);
});
}
/**
* Generates url with bot token and provided path/method you want to be got/executed by bot * Generates url with bot token and provided path/method you want to be got/executed by bot
* @return {String} url * @return {String} url
* @param {String} path * @param {String} path
* @private * @private
* @see https://core.telegram.org/bots/api#making-requests * @see https://core.telegram.org/bots/api#making-requests
*/ */
TelegramBot.prototype._buildURL = function(path) { _buildURL(_path) {
return URL.format({ return URL.format({
protocol: 'https', protocol: 'https',
host: 'api.telegram.org', host: 'api.telegram.org',
pathname: '/bot' + this.token + '/' + path pathname: `/bot${this.token}/${_path}`
}); });
}; }
/** /**
* Returns basic information about the bot in form of a `User` object. * Returns basic information about the bot in form of a `User` object.
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#getme * @see https://core.telegram.org/bots/api#getme
*/ */
TelegramBot.prototype.getMe = function () { getMe() {
var path = 'getMe'; const _path = 'getMe';
return this._request(path); return this._request(_path);
}; }
/** /**
* Specify an url to receive incoming updates via an outgoing webHook. * Specify an url to receive incoming updates via an outgoing webHook.
* @param {String} url URL where Telegram will make HTTP Post. Leave empty to * @param {String} url URL where Telegram will make HTTP Post. Leave empty to
* delete webHook. * delete webHook.
* @param {String|stream.Stream} [cert] PEM certificate key (public). * @param {String|stream.Stream} [cert] PEM certificate key (public).
* @see https://core.telegram.org/bots/api#setwebhook * @see https://core.telegram.org/bots/api#setwebhook
*/ */
TelegramBot.prototype.setWebHook = function (url, cert) { setWebHook(url, cert) {
var path = 'setWebHook'; const _path = 'setWebHook';
var opts = { const opts = { qs: { url } };
qs: {url: url}
};
if (cert) { if (cert) {
var content = this._formatSendData('certificate', cert); const [formData, certificate] = this._formatSendData('certificate', cert);
opts.formData = content[0]; opts.formData = formData;
opts.qs.certificate = content[1]; opts.qs.certificate = certificate;
} }
return this._request(path, opts) return this._request(_path, opts)
.then(function (resp) { .then(resp => {
if (!resp) { if (!resp) {
throw new Error(resp); throw new Error(resp);
} }
return resp; return resp;
}); });
}; }
/** /**
* Use this method to receive incoming updates using long polling * Use this method to receive incoming updates using long polling
* @param {Number|String} [timeout] Timeout in seconds for long polling. * @param {Number|String} [timeout] Timeout in seconds for long polling.
* @param {Number|String} [limit] Limits the number of updates to be retrieved. * @param {Number|String} [limit] Limits the number of updates to be retrieved.
@ -210,17 +214,17 @@ TelegramBot.prototype.setWebHook = function (url, cert) {
* @return {Promise} Updates * @return {Promise} Updates
* @see https://core.telegram.org/bots/api#getupdates * @see https://core.telegram.org/bots/api#getupdates
*/ */
TelegramBot.prototype.getUpdates = function (timeout, limit, offset) { getUpdates(timeout, limit, offset) {
var form = { const form = {
offset: offset, offset,
limit: limit, limit,
timeout: timeout timeout,
}; };
return this._request('getUpdates', {form: form}); return this._request('getUpdates', { form });
}; }
/** /**
* Send text message. * Send text message.
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
* @param {String} text Text of the message to be sent * @param {String} text Text of the message to be sent
@ -228,14 +232,13 @@ TelegramBot.prototype.getUpdates = function (timeout, limit, offset) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendmessage * @see https://core.telegram.org/bots/api#sendmessage
*/ */
TelegramBot.prototype.sendMessage = function (chatId, text, options) { sendMessage(chatId, text, form = {}) {
var form = options || {};
form.chat_id = chatId; form.chat_id = chatId;
form.text = text; form.text = text;
return this._request('sendMessage', {form: form}); return this._request('sendMessage', { form });
}; }
/** /**
* Send answers to an inline query. * Send answers to an inline query.
* @param {String} inlineQueryId Unique identifier of the query * @param {String} inlineQueryId Unique identifier of the query
* @param {InlineQueryResult[]} results An array of results for the inline query * @param {InlineQueryResult[]} results An array of results for the inline query
@ -243,15 +246,13 @@ TelegramBot.prototype.sendMessage = function (chatId, text, options) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#answerinlinequery * @see https://core.telegram.org/bots/api#answerinlinequery
*/ */
TelegramBot.prototype.answerInlineQuery = function (inlineQueryId, results, options) { answerInlineQuery(inlineQueryId, results, form = {}) {
var form = options || {};
form.inline_query_id = inlineQueryId; form.inline_query_id = inlineQueryId;
form.results = JSON.stringify(results); form.results = JSON.stringify(results);
return this._request('answerInlineQuery', {form: form}); return this._request('answerInlineQuery', { form });
}; }
/**
/**
* Forward messages of any kind. * Forward messages of any kind.
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
* @param {Number|String} fromChatId Unique identifier for the chat where the * @param {Number|String} fromChatId Unique identifier for the chat where the
@ -259,19 +260,20 @@ TelegramBot.prototype.answerInlineQuery = function (inlineQueryId, results, opti
* @param {Number|String} messageId Unique message identifier * @param {Number|String} messageId Unique message identifier
* @return {Promise} * @return {Promise}
*/ */
TelegramBot.prototype.forwardMessage = function (chatId, fromChatId, messageId) { forwardMessage(chatId, fromChatId, messageId) {
var form = { const form = {
chat_id: chatId, chat_id: chatId,
from_chat_id: fromChatId, from_chat_id: fromChatId,
message_id: messageId message_id: messageId
}; };
return this._request('forwardMessage', {form: form});
};
TelegramBot.prototype._formatSendData = function (type, data) { return this._request('forwardMessage', { form });
var formData; }
var fileName;
var fileId; _formatSendData(type, data) {
let formData;
let fileName;
let fileId;
if (data instanceof stream.Stream) { if (data instanceof stream.Stream) {
fileName = URL.parse(path.basename(data.path)).pathname; fileName = URL.parse(path.basename(data.path)).pathname;
formData = {}; formData = {};
@ -283,7 +285,7 @@ TelegramBot.prototype._formatSendData = function (type, data) {
} }
}; };
} else if (Buffer.isBuffer(data)) { } else if (Buffer.isBuffer(data)) {
var filetype = fileType(data); const filetype = fileType(data);
if (!filetype) { if (!filetype) {
throw new Error('Unsupported Buffer file type'); throw new Error('Unsupported Buffer file type');
} }
@ -291,7 +293,7 @@ TelegramBot.prototype._formatSendData = function (type, data) {
formData[type] = { formData[type] = {
value: data, value: data,
options: { options: {
filename: 'data.' + filetype.ext, filename: `data.${filetype.ext}`,
contentType: filetype.mime contentType: filetype.mime
} }
}; };
@ -309,9 +311,9 @@ TelegramBot.prototype._formatSendData = function (type, data) {
fileId = data; fileId = data;
} }
return [formData, fileId]; return [formData, fileId];
}; }
/** /**
* Send photo * Send photo
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
* @param {String|stream.Stream|Buffer} photo A file path or a Stream. Can * @param {String|stream.Stream|Buffer} photo A file path or a Stream. Can
@ -320,18 +322,18 @@ TelegramBot.prototype._formatSendData = function (type, data) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendphoto * @see https://core.telegram.org/bots/api#sendphoto
*/ */
TelegramBot.prototype.sendPhoto = function (chatId, photo, options) { sendPhoto(chatId, photo, options = {}) {
var opts = { const opts = {
qs: options || {} qs: options,
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
var content = this._formatSendData('photo', photo); const content = this._formatSendData('photo', photo);
opts.formData = content[0]; opts.formData = content[0];
opts.qs.photo = content[1]; opts.qs.photo = content[1];
return this._request('sendPhoto', opts); return this._request('sendPhoto', opts);
}; }
/** /**
* Send audio * Send audio
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
* @param {String|stream.Stream|Buffer} audio A file path, Stream or Buffer. * @param {String|stream.Stream|Buffer} audio A file path, Stream or Buffer.
@ -340,18 +342,18 @@ TelegramBot.prototype.sendPhoto = function (chatId, photo, options) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendaudio * @see https://core.telegram.org/bots/api#sendaudio
*/ */
TelegramBot.prototype.sendAudio = function (chatId, audio, options) { sendAudio(chatId, audio, options = {}) {
var opts = { const opts = {
qs: options || {} qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
var content = this._formatSendData('audio', audio); const content = this._formatSendData('audio', audio);
opts.formData = content[0]; opts.formData = content[0];
opts.qs.audio = content[1]; opts.qs.audio = content[1];
return this._request('sendAudio', opts); return this._request('sendAudio', opts);
}; }
/** /**
* Send Document * Send Document
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
* @param {String|stream.Stream|Buffer} doc A file path, Stream or Buffer. * @param {String|stream.Stream|Buffer} doc A file path, Stream or Buffer.
@ -360,18 +362,18 @@ TelegramBot.prototype.sendAudio = function (chatId, audio, options) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendDocument * @see https://core.telegram.org/bots/api#sendDocument
*/ */
TelegramBot.prototype.sendDocument = function (chatId, doc, options) { sendDocument(chatId, doc, options = {}) {
var opts = { const opts = {
qs: options || {} qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
var content = this._formatSendData('document', doc); const content = this._formatSendData('document', doc);
opts.formData = content[0]; opts.formData = content[0];
opts.qs.document = content[1]; opts.qs.document = content[1];
return this._request('sendDocument', opts); return this._request('sendDocument', opts);
}; }
/** /**
* Send .webp stickers. * Send .webp stickers.
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
* @param {String|stream.Stream|Buffer} sticker A file path, Stream or Buffer. * @param {String|stream.Stream|Buffer} sticker A file path, Stream or Buffer.
@ -380,18 +382,18 @@ TelegramBot.prototype.sendDocument = function (chatId, doc, options) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendsticker * @see https://core.telegram.org/bots/api#sendsticker
*/ */
TelegramBot.prototype.sendSticker = function (chatId, sticker, options) { sendSticker(chatId, sticker, options = {}) {
var opts = { const opts = {
qs: options || {} qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
var content = this._formatSendData('sticker', sticker); const content = this._formatSendData('sticker', sticker);
opts.formData = content[0]; opts.formData = content[0];
opts.qs.sticker = content[1]; opts.qs.sticker = content[1];
return this._request('sendSticker', opts); return this._request('sendSticker', opts);
}; }
/** /**
* Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). * Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document).
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
* @param {String|stream.Stream|Buffer} video A file path or Stream. * @param {String|stream.Stream|Buffer} video A file path or Stream.
@ -400,18 +402,18 @@ TelegramBot.prototype.sendSticker = function (chatId, sticker, options) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendvideo * @see https://core.telegram.org/bots/api#sendvideo
*/ */
TelegramBot.prototype.sendVideo = function (chatId, video, options) { sendVideo(chatId, video, options = {}) {
var opts = { const opts = {
qs: options || {} qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
var content = this._formatSendData('video', video); const content = this._formatSendData('video', video);
opts.formData = content[0]; opts.formData = content[0];
opts.qs.video = content[1]; opts.qs.video = content[1];
return this._request('sendVideo', opts); return this._request('sendVideo', opts);
}; }
/** /**
* Send voice * Send voice
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
* @param {String|stream.Stream|Buffer} voice A file path, Stream or Buffer. * @param {String|stream.Stream|Buffer} voice A file path, Stream or Buffer.
@ -420,19 +422,19 @@ TelegramBot.prototype.sendVideo = function (chatId, video, options) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendvoice * @see https://core.telegram.org/bots/api#sendvoice
*/ */
TelegramBot.prototype.sendVoice = function (chatId, voice, options) { sendVoice(chatId, voice, options = {}) {
var opts = { const opts = {
qs: options || {} qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
var content = this._formatSendData('voice', voice); const content = this._formatSendData('voice', voice);
opts.formData = content[0]; opts.formData = content[0];
opts.qs.voice = content[1]; opts.qs.voice = content[1];
return this._request('sendVoice', opts); return this._request('sendVoice', opts);
}; }
/** /**
* Send chat action. * Send chat action.
* `typing` for text messages, * `typing` for text messages,
* `upload_photo` for photos, `record_video` or `upload_video` for videos, * `upload_photo` for photos, `record_video` or `upload_video` for videos,
@ -444,15 +446,15 @@ TelegramBot.prototype.sendVoice = function (chatId, voice, options) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendchataction * @see https://core.telegram.org/bots/api#sendchataction
*/ */
TelegramBot.prototype.sendChatAction = function (chatId, action) { sendChatAction(chatId, action) {
var form = { const form = {
chat_id: chatId, action,
action: action chat_id: chatId
}; };
return this._request('sendChatAction', {form: form}); return this._request('sendChatAction', { form });
}; }
/** /**
* Use this method to get a list of profile pictures for a user. * Use this method to get a list of profile pictures for a user.
* Returns a [UserProfilePhotos](https://core.telegram.org/bots/api#userprofilephotos) object. * Returns a [UserProfilePhotos](https://core.telegram.org/bots/api#userprofilephotos) object.
* *
@ -462,16 +464,16 @@ TelegramBot.prototype.sendChatAction = function (chatId, action) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#getuserprofilephotos * @see https://core.telegram.org/bots/api#getuserprofilephotos
*/ */
TelegramBot.prototype.getUserProfilePhotos = function (userId, offset, limit) { getUserProfilePhotos(userId, offset, limit) {
var form = { const form = {
user_id: userId, user_id: userId,
offset: offset, offset,
limit: limit limit
}; };
return this._request('getUserProfilePhotos', {form: form}); return this._request('getUserProfilePhotos', { form });
}; }
/** /**
* Send location. * Send location.
* Use this method to send point on the map. * Use this method to send point on the map.
* *
@ -482,15 +484,14 @@ TelegramBot.prototype.getUserProfilePhotos = function (userId, offset, limit) {
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendlocation * @see https://core.telegram.org/bots/api#sendlocation
*/ */
TelegramBot.prototype.sendLocation = function (chatId, latitude, longitude, options) { sendLocation(chatId, latitude, longitude, form = {}) {
var form = options || {};
form.chat_id = chatId; form.chat_id = chatId;
form.latitude = latitude; form.latitude = latitude;
form.longitude = longitude; form.longitude = longitude;
return this._request('sendLocation', {form: form}); return this._request('sendLocation', { form });
}; }
/** /**
* Get file. * Get file.
* Use this method to get basic info about a file and prepare it for downloading. * Use this method to get basic info about a file and prepare it for downloading.
* Attention: link will be valid for 1 hour. * Attention: link will be valid for 1 hour.
@ -499,34 +500,33 @@ TelegramBot.prototype.sendLocation = function (chatId, latitude, longitude, opti
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#getfile * @see https://core.telegram.org/bots/api#getfile
*/ */
TelegramBot.prototype.getFile = function(fileId) { getFile(fileId) {
var form = {file_id: fileId}; const form = { file_id: fileId };
return this._request('getFile', {form: form}); return this._request('getFile', { form });
}; }
/** /**
* Get link for file. * Get link for file.
* Use this method to get link for file for subsequent use. * Use this method to get link for file for subsequent use.
* Attention: link will be valid for 1 hour. * Attention: link will be valid for 1 hour.
* *
* This method is a sugar extension of the (getFile)[#getfilefileid] method, which returns just path to file on remote server (you will have to manually build full uri after that). * This method is a sugar extension of the (getFile)[#getfilefileid] method,
* which returns just path to file on remote server (you will have to manually build full uri after that).
* *
* @param {String} fileId File identifier to get info about * @param {String} fileId File identifier to get info about
* @return {Promise} promise Promise which will have *fileURI* in resolve callback * @return {Promise} promise Promise which will have *fileURI* in resolve callback
* @see https://core.telegram.org/bots/api#getfile * @see https://core.telegram.org/bots/api#getfile
*/ */
TelegramBot.prototype.getFileLink = function(fileId) { getFileLink(fileId) {
return this.getFile(fileId) return this.getFile(fileId)
.then(function (resp) { .then(resp => URL.format({
return URL.format({
protocol: 'https', protocol: 'https',
host: 'api.telegram.org', host: 'api.telegram.org',
pathname: '/file/bot' + this.token + '/' + resp.file_path pathname: `/file/bot${this.token}/${resp.file_path}`
}); }));
}.bind(this)); }
};
/** /**
* Downloads file in the specified folder. * Downloads file in the specified folder.
* This is just a sugar for (getFile)[#getfilefiled] method * This is just a sugar for (getFile)[#getfilefiled] method
* *
@ -534,47 +534,47 @@ TelegramBot.prototype.getFileLink = function(fileId) {
* @param {String} downloadDir Absolute path to the folder in which file will be saved * @param {String} downloadDir Absolute path to the folder in which file will be saved
* @return {Promise} promise Promise, which will have *filePath* of downloaded file in resolve callback * @return {Promise} promise Promise, which will have *filePath* of downloaded file in resolve callback
*/ */
TelegramBot.prototype.downloadFile = function(fileId, downloadDir) { downloadFile(fileId, downloadDir) {
return this
return this.getFileLink(fileId).then(function (fileURI) { .getFileLink(fileId)
var fileName = fileURI.slice(fileURI.lastIndexOf('/') + 1); .then(fileURI => {
const fileName = fileURI.slice(fileURI.lastIndexOf('/') + 1);
// TODO: Ensure fileName doesn't contains slashes // TODO: Ensure fileName doesn't contains slashes
var filePath = downloadDir + '/' + fileName; const filePath = `${downloadDir}/${fileName}`;
return new Promise(function (resolve, reject) {
request({uri: fileURI})
.pipe(fs.createWriteStream(filePath))
.on('error', reject)
.on('close', function() {
resolve(filePath);
});
});
});
}; // properly handles errors and closes all streams
return Promise
.fromCallback(next => {
pump(streamedRequest({ uri: fileURI }), fs.createWriteStream(filePath), next);
})
.return(filePath);
});
}
/** /**
* Register a RegExp to test against an incomming text message. * Register a RegExp to test against an incomming text message.
* @param {RegExp} regexp RegExp to be executed with `exec`. * @param {RegExp} regexp RegExp to be executed with `exec`.
* @param {Function} callback Callback will be called with 2 parameters, * @param {Function} callback Callback will be called with 2 parameters,
* the `msg` and the result of executing `regexp.exec` on message text. * the `msg` and the result of executing `regexp.exec` on message text.
*/ */
TelegramBot.prototype.onText = function (regexp, callback) { onText(regexp, callback) {
this.textRegexpCallbacks.push({regexp: regexp, callback: callback}); this.textRegexpCallbacks.push({ regexp, callback });
}; }
/** /**
* Register a reply to wait for a message response. * Register a reply to wait for a message response.
* @param {Number|String} chatId The chat id where the message cames from. * @param {Number|String} chatId The chat id where the message cames from.
* @param {Number|String} messageId The message id to be replied. * @param {Number|String} messageId The message id to be replied.
* @param {Function} callback Callback will be called with the reply * @param {Function} callback Callback will be called with the reply
* message. * message.
*/ */
TelegramBot.prototype.onReplyToMessage = function (chatId, messageId, callback) { onReplyToMessage(chatId, messageId, callback) {
this.onReplyToMessages.push({ this.onReplyToMessages.push({
chatId: chatId, chatId,
messageId: messageId, messageId,
callback: callback callback
}); });
}; }
}
module.exports = TelegramBot; module.exports = TelegramBot;

View File

@ -1,19 +1,21 @@
'use strict'; const Promise = require('bluebird');
const debug = require('debug')('node-telegram-bot-api');
const request = require('request-promise');
const URL = require('url');
var debug = require('debug')('node-telegram-bot-api'); class TelegramBotPolling {
var Promise = require('bluebird');
var request = require('request');
var util = require('util');
var URL = require('url');
var requestPromise = Promise.promisify(request); constructor(token, options = {}, callback) {
// enable cancellation
Promise.config({
cancellation: true,
});
var TelegramBotPolling = function (token, options, callback) {
options = options || {};
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options; callback = options; // eslint-disable-line no-param-reassign
options = {}; options = {}; // eslint-disable-line no-param-reassign
} }
this.offset = 0; this.offset = 0;
this.token = token; this.token = token;
this.callback = callback; this.callback = callback;
@ -23,68 +25,79 @@ var TelegramBotPolling = function (token, options, callback) {
this.lastRequest = null; this.lastRequest = null;
this.abort = false; this.abort = false;
this._polling(); this._polling();
}; }
TelegramBotPolling.prototype._polling = function () { _polling() {
this.lastRequest = this._getUpdates() this.lastRequest = this
.then(function (updates) { ._getUpdates()
.then(updates => {
this.lastUpdate = Date.now(); this.lastUpdate = Date.now();
debug('polling data %j', updates); debug('polling data %j', updates);
updates.forEach(function (update, index) { updates.forEach(update => {
this.offset = update.update_id; this.offset = update.update_id;
debug('updated offset: %s', this.offset); debug('updated offset: %s', this.offset);
this.callback(update); this.callback(update);
}.bind(this)); });
}.bind(this)) })
.catch(function (err) { .catch(err => {
debug('polling error: %s', err.message); debug('polling error: %s', err.message);
throw err; throw err;
}) })
.finally(function () { .finally(() => {
if (this.abort) { if (this.abort) {
debug('Polling is aborted!'); debug('Polling is aborted!');
} else { } else {
debug('setTimeout for %s miliseconds', this.interval); debug('setTimeout for %s miliseconds', this.interval);
setTimeout(this._polling.bind(this), this.interval); setTimeout(() => this._polling(), this.interval);
}
});
} }
}.bind(this));
};
TelegramBotPolling.prototype._getUpdates = function () { // used so that other funcs are not non-optimizable
var opts = { _safeParse(json) {
try {
return JSON.parse(json);
} catch (err) {
throw new Error(`Error parsing Telegram response: ${String(json)}`);
}
}
_getUpdates() {
const opts = {
qs: { qs: {
offset: this.offset+1, offset: this.offset + 1,
limit: this.limit, limit: this.limit,
timeout: this.timeout timeout: this.timeout
}, },
url: URL.format({ url: URL.format({
protocol: 'https', protocol: 'https',
host: 'api.telegram.org', host: 'api.telegram.org',
pathname: '/bot'+this.token+'/getUpdates' pathname: `/bot${this.token}/getUpdates`
}) }),
simple: false,
resolveWithFullResponse: true,
forever: true,
}; };
debug('polling with options: %j', opts); debug('polling with options: %j', opts);
return requestPromise(opts)
.cancellable() return request(opts)
.promise()
.timeout((10 + this.timeout) * 1000) .timeout((10 + this.timeout) * 1000)
.then(function (resp) { .then(resp => {
if (resp[0].statusCode !== 200) { if (resp.statusCode !== 200) {
throw new Error(resp[0].statusCode+' '+resp[0].body); throw new Error(`${resp.statusCode} ${resp.body}`);
}
var data;
try {
data = JSON.parse(resp[0].body);
} catch (err) {
var text = util.format('Error parsing Telegram response: %s',
resp[0].body);
throw new Error(text);
} }
const data = this._safeParse(resp.body);
if (data.ok) { if (data.ok) {
return data.result; return data.result;
} else {
throw new Error(data.error_code+' '+data.description);
} }
throw new Error(`${data.error_code} ${data.description}`);
}); });
}; }
}
module.exports = TelegramBotPolling; module.exports = TelegramBotPolling;

View File

@ -1,67 +1,85 @@
'use strict'; const debug = require('debug')('node-telegram-bot-api');
const https = require('https');
const http = require('http');
const fs = require('fs');
const bl = require('bl');
var debug = require('debug')('node-telegram-bot-api'); class TelegramBotWebHook {
var https = require('https');
var http = require('http');
var fs = require('fs');
var TelegramBotWebHook = function (token, options, callback) { constructor(token, options, callback) {
this.token = token; this.token = token;
this.callback = callback; this.callback = callback;
this.regex = new RegExp(this.token);
// define opts
if (typeof options === 'boolean') { if (typeof options === 'boolean') {
options = {}; options = {}; // eslint-disable-line no-param-reassign
} }
options.port = options.port || 8443; options.port = options.port || 8443;
var binded = this._requestListener.bind(this);
if (options.key && options.cert) { // HTTPS Server if (options.key && options.cert) { // HTTPS Server
debug('HTTPS WebHook enabled'); debug('HTTPS WebHook enabled');
var opts = { const opts = {
key: fs.readFileSync(options.key), key: fs.readFileSync(options.key),
cert: fs.readFileSync(options.cert) cert: fs.readFileSync(options.cert)
}; };
this._webServer = https.createServer(opts, binded); this._webServer = https.createServer(opts, this._requestListener);
} else { } else {
debug('HTTP WebHook enabled'); debug('HTTP WebHook enabled');
this._webServer = http.createServer(binded); this._webServer = http.createServer(this._requestListener);
} }
this._webServer.listen(options.port, options.host, function () { this._webServer.listen(options.port, options.host, () => {
debug('WebHook listening on port %s', options.port); debug('WebHook listening on port %s', options.port);
}); });
}; }
TelegramBotWebHook.prototype._requestListener = function (req, res) { // used so that other funcs are not non-optimizable
var self = this; _safeParse(json) {
var regex = new RegExp(this.token); try {
return JSON.parse(json);
} catch (err) {
debug(err);
return null;
}
}
// pipe+parse body
_parseBody = (err, body) => {
if (err) {
return debug(err);
}
const data = this._safeParse(body);
if (data) {
return this.callback(data);
}
return null;
}
// bound req listener
_requestListener = (req, res) => {
debug('WebHook request URL:', req.url); debug('WebHook request URL:', req.url);
debug('WebHook request headers: %j', req.headers); debug('WebHook request headers: %j', req.headers);
// If there isn't token on URL // If there isn't token on URL
if (!regex.test(req.url)) { if (!this.regex.test(req.url)) {
debug('WebHook request unauthorized'); debug('WebHook request unauthorized');
res.statusCode = 401; res.statusCode = 401;
res.end(); res.end();
} else if (req.method === 'POST') { } else if (req.method === 'POST') {
var fullBody = ''; req
req.on('data', function (chunk) { .pipe(bl(this._parseBody))
fullBody += chunk.toString(); .on('end', () => res.end('OK'));
}); } else {
req.on('end', function () { // Authorized but not a POST
try {
debug('WebHook request fullBody', fullBody);
var data = JSON.parse(fullBody);
self.callback(data);
} catch (error) {
debug(error);
}
res.end('OK');
});
} else { // Authorized but not a POST
debug('WebHook request isn\'t a POST'); debug('WebHook request isn\'t a POST');
res.statusCode = 418; // I'm a teabot! res.statusCode = 418; // I'm a teabot!
res.end(); res.end();
} }
}; }
}
module.exports = TelegramBotWebHook; module.exports = TelegramBotWebHook;

View File

@ -1,12 +0,0 @@
{
"mocha" : true,
"curly" : true,
"eqeqeq" : true,
"indent" : 2,
"latedef" : true,
"newcap" : true,
"quotmark": "single",
"strict" : true,
"undef" : true,
"node" : true
}

View File

@ -1,533 +1,506 @@
'use strict'; const TelegramPolling = require('../src/telegramPolling');
const Telegram = require('../index');
var TelegramPolling = require('../src/telegramPolling'); const Promise = require('bluebird');
var Telegram = require('../index'); const request = require('request-promise');
var Promise = require('bluebird'); const assert = require('assert');
var request = require('request'); const fs = require('fs');
var should = require('should'); const is = require('is');
var fs = require('fs');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
var TOKEN = process.env.TEST_TELEGRAM_TOKEN; const TOKEN = process.env.TEST_TELEGRAM_TOKEN;
if (!TOKEN) { if (!TOKEN) {
throw new Error('Bot token not provided'); throw new Error('Bot token not provided');
} }
// Telegram service if not User Id // Telegram service if not User Id
var USERID = process.env.TEST_USER_ID || 777000; const USERID = process.env.TEST_USER_ID || 777000;
describe('Telegram', function () { describe('Telegram', function telegramSuite() {
describe('#setWebHook', function setWebHookSuite() {
describe('#setWebHook', function () { it('should set a webHook', function test() {
it('should set a webHook', function (done) { const bot = new Telegram(TOKEN);
var bot = new Telegram(TOKEN);
// Google IP ¯\_(ツ)_/¯ // Google IP ¯\_(ツ)_/¯
bot.setWebHook('216.58.210.174').then(function (resp) { return bot
resp.should.be.exactly(true); .setWebHook('216.58.210.174')
done(); .then(resp => {
assert.equal(resp, true);
}); });
}); });
it('should set a webHook with certificate', function (done) { it('should set a webHook with certificate', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var cert = __dirname+'/../examples/crt.pem'; const cert = `${__dirname}/../examples/crt.pem`;
bot.setWebHook('216.58.210.174', cert).then(function (resp) { return bot
resp.should.be.exactly(true); .setWebHook('216.58.210.174', cert)
done(); .then(resp => {
assert.equal(resp, true);
}); });
}); });
it('should delete the webHook', function (done) { it('should delete the webHook', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
bot.setWebHook('').then(function (resp) { return bot
resp.should.be.exactly(true); .setWebHook('')
done(); .then(resp => {
assert.equal(resp, true);
}); });
}); });
}); });
describe('#WebHook', function () { describe('#WebHook', function WebHookSuite() {
it('should reject request if same token not provided', function (done) { it('should reject request if same token not provided', function test() {
var bot = new Telegram(TOKEN, {webHook: true}); const bot = new Telegram(TOKEN, { webHook: true });
request({
return request({
url: 'http://localhost:8443/NOT_REAL_TOKEN', url: 'http://localhost:8443/NOT_REAL_TOKEN',
method: 'POST' method: 'POST',
}, function (error, response, body) { simple: false,
response.statusCode.should.not.be.equal(200); resolveWithFullResponse: true
}).then(response => {
assert.notEqual(response.statusCode, 200);
bot._WebHook._webServer.close(); bot._WebHook._webServer.close();
done();
}); });
}); });
it('should reject request if authorized but not a POST', function (done) { it('should reject request if authorized but not a POST', function test() {
var bot = new Telegram(TOKEN, {webHook: true}); const bot = new Telegram(TOKEN, { webHook: true });
request({ return request({
url: 'http://localhost:8443/bot'+TOKEN, url: `http://localhost:8443/bot${TOKEN}`,
method: 'GET' method: 'GET',
}, function (error, response, body) { simple: false,
response.statusCode.should.not.be.equal(200); resolveWithFullResponse: true
})
.then(response => {
assert.notEqual(response.statusCode, 200);
bot._WebHook._webServer.close(); bot._WebHook._webServer.close();
done();
}); });
}); });
it('should emit a `message` on HTTP WebHook', function (done) { it('should emit a `message` on HTTP WebHook', function test(done) {
var bot = new Telegram(TOKEN, {webHook: true}); const bot = new Telegram(TOKEN, { webHook: true });
bot.on('message', function (msg) { bot.on('message', () => {
bot._WebHook._webServer.close(); bot._WebHook._webServer.close();
done(); done();
}); });
var url = 'http://localhost:8443/bot'+TOKEN;
const url = `http://localhost:8443/bot${TOKEN}`;
request({ request({
url: url, url,
method: 'POST', method: 'POST',
json: true, json: true,
headers: { headers: {
'content-type': 'application/json', 'content-type': 'application/json',
}, },
body: {update_id: 0, message: {text: 'test'}} body: { update_id: 0, message: { text: 'test' } }
}); });
}); });
it('should emit a `message` on HTTPS WebHook', function (done) { it('should emit a `message` on HTTPS WebHook', function test(done) {
var opts = { const opts = {
webHook: { webHook: {
port: 8443, port: 8443,
key: __dirname+'/../examples/key.pem', key: `${__dirname}/../examples/key.pem`,
cert: __dirname+'/../examples/crt.pem' cert: `${__dirname}/../examples/crt.pem`
} }
}; };
var bot = new Telegram(TOKEN, opts); const bot = new Telegram(TOKEN, opts);
bot.on('message', function (msg) { bot.on('message', () => {
bot._WebHook._webServer.close(); bot._WebHook._webServer.close();
done(); done();
}); });
var url = 'https://localhost:8443/bot'+TOKEN; const url = `https://localhost:8443/bot${TOKEN}`;
request({ request({
url: url, url,
method: 'POST', method: 'POST',
json: true, json: true,
headers: { headers: {
'content-type': 'application/json', 'content-type': 'application/json',
}, },
rejectUnhauthorized: false, rejectUnhauthorized: false,
body: {update_id: 0, message: {text: 'test'}} body: { update_id: 0, message: { text: 'test' } }
}); });
}); });
}); });
describe('#getMe', function () { describe('#getMe', function getMeSuite() {
it('should return an User object', function (done) { it('should return an User object', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
bot.getMe().then(function (resp) { return bot.getMe().then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
}); });
describe('#getUpdates', function () { describe('#getUpdates', function getUpdatesSuite() {
it('should return an Array', function (done) { it('should return an Array', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
bot.getUpdates().then(function (resp) { return bot.getUpdates().then(resp => {
resp.should.be.an.instanceOf(Array); assert.equal(Array.isArray(resp), true);
done();
}); });
}); });
}); });
describe('#sendMessage', function () { describe('#sendMessage', function sendMessageSuite() {
it('should send a message', function (done) { it('should send a message', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
bot.sendMessage(USERID, 'test').then(function (resp) { return bot.sendMessage(USERID, 'test').then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
}); });
describe('#forwardMessage', function () { describe('#forwardMessage', function forwardMessageSuite() {
it('should forward a message', function (done) { it('should forward a message', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
bot.sendMessage(USERID, 'test').then(function (resp) { return bot.sendMessage(USERID, 'test').then(resp => {
var messageId = resp.message_id; const messageId = resp.message_id;
bot.forwardMessage(USERID, USERID, messageId) return bot.forwardMessage(USERID, USERID, messageId)
.then(function (resp) { .then(forwarded => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(forwarded));
done();
}); });
}); });
}); });
}); });
describe('#sendPhoto', function () { describe('#sendPhoto', function sendPhotoSuite() {
var photoId; let photoId;
it('should send a photo from file', function (done) { it('should send a photo from file', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var photo = __dirname+'/bot.gif'; const photo = `${__dirname}/bot.gif`;
bot.sendPhoto(USERID, photo).then(function (resp) { return bot.sendPhoto(USERID, photo).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
photoId = resp.photo[0].file_id; photoId = resp.photo[0].file_id;
done();
}); });
}); });
it('should send a photo from id', function (done) { it('should send a photo from id', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
// Send the same photo as before // Send the same photo as before
var photo = photoId; const photo = photoId;
bot.sendPhoto(USERID, photo).then(function (resp) { return bot.sendPhoto(USERID, photo).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a photo from fs.readStream', function (done) { it('should send a photo from fs.readStream', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var photo = fs.createReadStream(__dirname+'/bot.gif'); const photo = fs.createReadStream(`${__dirname}/bot.gif`);
bot.sendPhoto(USERID, photo).then(function (resp) { return bot.sendPhoto(USERID, photo).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a photo from request Stream', function (done) { it('should send a photo from request Stream', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var photo = request('https://telegram.org/img/t_logo.png'); const photo = request('https://telegram.org/img/t_logo.png');
bot.sendPhoto(USERID, photo).then(function (resp) { return bot.sendPhoto(USERID, photo).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a photo from a Buffer', function (done) { it('should send a photo from a Buffer', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var photo = fs.readFileSync(__dirname+'/bot.gif'); const photo = fs.readFileSync(`${__dirname}/bot.gif`);
bot.sendPhoto(USERID, photo).then(function (resp) { return bot.sendPhoto(USERID, photo).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
}); });
describe('#sendChatAction', function () { describe('#sendChatAction', function sendChatActionSuite() {
it('should send a chat action', function (done) { it('should send a chat action', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var action = 'typing'; const action = 'typing';
bot.sendChatAction(USERID, action).then(function (resp) { return bot.sendChatAction(USERID, action).then(resp => {
resp.should.be.exactly(true); assert.equal(resp, true);
done();
}); });
}); });
}); });
describe('#sendAudio', function () { describe('#sendAudio', function sendAudioSuite() {
it('should send an OGG audio', function (done) { it('should send an OGG audio', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var audio = request('https://upload.wikimedia.org/wikipedia/commons/c/c8/Example.ogg'); const audio = request('https://upload.wikimedia.org/wikipedia/commons/c/c8/Example.ogg');
bot.sendAudio(USERID, audio).then(function (resp) { return bot.sendAudio(USERID, audio).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
}); });
describe('#sendDocument', function () { describe('#sendDocument', function sendDocumentSuite() {
var documentId; let documentId;
it('should send a document from file', function (done) { it('should send a document from file', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var document = __dirname+'/bot.gif'; const document = `${__dirname}/bot.gif`;
bot.sendDocument(USERID, document).then(function (resp) { return bot.sendDocument(USERID, document).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
documentId = resp.document.file_id; documentId = resp.document.file_id;
done();
}); });
}); });
it('should send a document from id', function (done) { it('should send a document from id', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
// Send the same photo as before // Send the same photo as before
var document = documentId; const document = documentId;
bot.sendDocument(USERID, document).then(function (resp) { return bot.sendDocument(USERID, document).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a document from fs.readStream', function (done) { it('should send a document from fs.readStream', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var document = fs.createReadStream(__dirname+'/bot.gif'); const document = fs.createReadStream(`${__dirname}/bot.gif`);
bot.sendDocument(USERID, document).then(function (resp) { return bot.sendDocument(USERID, document).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a document from request Stream', function (done) { it('should send a document from request Stream', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var document = request('https://telegram.org/img/t_logo.png'); const document = request('https://telegram.org/img/t_logo.png');
bot.sendDocument(USERID, document).then(function (resp) { return bot.sendDocument(USERID, document).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a document from a Buffer', function (done) { it('should send a document from a Buffer', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var document = fs.readFileSync(__dirname+'/bot.gif'); const document = fs.readFileSync(`${__dirname}/bot.gif`);
bot.sendDocument(USERID, document).then(function (resp) { return bot.sendDocument(USERID, document).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
}); });
describe('#sendSticker', function () { describe('#sendSticker', function sendStickerSuite() {
var stickerId; let stickerId;
it('should send a sticker from file', function (done) { it('should send a sticker from file', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var sticker = __dirname+'/sticker.webp'; const sticker = `${__dirname}/sticker.webp`;
bot.sendSticker(USERID, sticker).then(function (resp) { return bot.sendSticker(USERID, sticker).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
stickerId = resp.sticker.file_id; stickerId = resp.sticker.file_id;
done();
}); });
}); });
it('should send a sticker from id', function (done) { it('should send a sticker from id', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
// Send the same photo as before // Send the same photo as before
bot.sendSticker(USERID, stickerId).then(function (resp) { return bot.sendSticker(USERID, stickerId).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a sticker from fs.readStream', function (done) { it('should send a sticker from fs.readStream', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var sticker = fs.createReadStream(__dirname+'/sticker.webp'); const sticker = fs.createReadStream(`${__dirname}/sticker.webp`);
bot.sendSticker(USERID, sticker).then(function (resp) { return bot.sendSticker(USERID, sticker).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a sticker from request Stream', function (done) { it('should send a sticker from request Stream', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var sticker = request('https://www.gstatic.com/webp/gallery3/1_webp_ll.webp'); const sticker = request('https://www.gstatic.com/webp/gallery3/1_webp_ll.webp');
bot.sendSticker(USERID, sticker).then(function (resp) { return bot.sendSticker(USERID, sticker).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a sticker from a Buffer', function (done) { it('should send a sticker from a Buffer', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var sticker = fs.readFileSync(__dirname+'/sticker.webp'); const sticker = fs.readFileSync(`${__dirname}/sticker.webp`);
bot.sendDocument(USERID, sticker).then(function (resp) { return bot.sendDocument(USERID, sticker).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
}); });
describe('#sendVideo', function () { describe('#sendVideo', function sendVideoSuite() {
var videoId; let videoId;
it('should send a video from file', function (done) { it('should send a video from file', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var video = __dirname+'/video.mp4'; const video = `${__dirname}/video.mp4`;
bot.sendVideo(USERID, video).then(function (resp) { return bot.sendVideo(USERID, video).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
videoId = resp.video.file_id; videoId = resp.video.file_id;
done();
}); });
}); });
it('should send a video from id', function (done) { it('should send a video from id', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
// Send the same photo as before // Send the same photo as before
bot.sendVideo(USERID, videoId).then(function (resp) { return bot.sendVideo(USERID, videoId).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a video from fs.readStream', function (done) { it('should send a video from fs.readStream', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var video = fs.createReadStream(__dirname+'/video.mp4'); const video = fs.createReadStream(`${__dirname}/video.mp4`);
bot.sendVideo(USERID, video).then(function (resp) { return bot.sendVideo(USERID, video).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a video from request Stream', function (done) { it('should send a video from request Stream', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var sticker = request('http://techslides.com/demos/sample-videos/small.mp4'); const sticker = request('http://techslides.com/demos/sample-videos/small.mp4');
bot.sendVideo(USERID, sticker).then(function (resp) { return bot.sendVideo(USERID, sticker).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
it('should send a video from a Buffer', function (done) { it('should send a video from a Buffer', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var video = fs.readFileSync(__dirname+'/video.mp4'); const video = fs.readFileSync(`${__dirname}/video.mp4`);
bot.sendVideo(USERID, video).then(function (resp) { return bot.sendVideo(USERID, video).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
}); });
describe('#sendVoice', function () { describe('#sendVoice', function sendVoiceSuite() {
it('should send an OGG audio as voice', function (done) { it('should send an OGG audio as voice', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var voice = request('https://upload.wikimedia.org/wikipedia/commons/c/c8/Example.ogg'); const voice = request('https://upload.wikimedia.org/wikipedia/commons/c/c8/Example.ogg');
bot.sendVoice(USERID, voice).then(function (resp) { return bot.sendVoice(USERID, voice).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
done();
}); });
}); });
}); });
describe('#getUserProfilePhotos', function () { describe('#getUserProfilePhotos', function getUserProfilePhotosSuite() {
it('should get user profile photos', function (done) { it('should get user profile photos', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
bot.getUserProfilePhotos(USERID).then(function (resp) { return bot.getUserProfilePhotos(USERID).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
resp.total_count.should.be.an.instanceOf(Number); assert.ok(is.number(resp.total_count));
resp.photos.should.be.an.instanceOf(Array); assert.ok(is.array(resp.photos));
done();
}); });
}); });
}); });
describe('#sendLocation', function () { describe('#sendLocation', function sendLocationSuite() {
it('should send a location', function (done) { it('should send a location', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var lat = 47.5351072; const lat = 47.5351072;
var long = -52.7508537; const long = -52.7508537;
bot.sendLocation(USERID, lat, long).then(function (resp) { return bot.sendLocation(USERID, lat, long).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
resp.location.should.be.an.instanceOf(Object); assert.ok(is.object(resp.location));
resp.location.latitude.should.be.an.instanceOf(Number); assert.ok(is.number(resp.location.latitude));
resp.location.longitude.should.be.an.instanceOf(Number); assert.ok(is.number(resp.location.longitude));
done();
}); });
}); });
}); });
describe('#getFile', function () { describe('#getFile', function getFileSuite() {
var fileId; let fileId;
// To get a file we have to send any file first // To get a file we have to send any file first
it('should send a photo from file', function (done) { it('should send a photo from file', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var photo = __dirname + '/bot.gif'; const photo = `${__dirname}/bot.gif`;
bot.sendPhoto(USERID, photo).then(function (resp) { return bot.sendPhoto(USERID, photo).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
fileId = resp.photo[0].file_id; fileId = resp.photo[0].file_id;
done();
}); });
}); });
it('should get a file', function (done) { it('should get a file', function test() {
const bot = new Telegram(TOKEN);
var bot = new Telegram(TOKEN); return bot
.getFile(fileId)
bot.getFile(fileId).then(function (resp) { .then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
resp.file_path.should.be.an.instanceOf(String); assert.ok(is.string(resp.file_path));
done();
}); });
}); });
}); });
describe('#getFileLink', function () { describe('#getFileLink', function getFileLinkSuite() {
var fileId; let fileId;
// To get a file we have to send any file first // To get a file we have to send any file first
it('should send a photo from file', function (done) { it('should send a photo from file', function test() {
var bot = new Telegram(TOKEN); const bot = new Telegram(TOKEN);
var photo = __dirname + '/bot.gif'; const photo = `${__dirname}/bot.gif`;
bot.sendPhoto(USERID, photo).then(function (resp) { return bot.sendPhoto(USERID, photo).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
fileId = resp.photo[0].file_id; fileId = resp.photo[0].file_id;
done();
}); });
}); });
it('should get a file link', function (done) { it('should get a file link', function test() {
const bot = new Telegram(TOKEN);
var bot = new Telegram(TOKEN); return bot
.getFileLink(fileId)
bot.getFileLink(fileId).then(function (fileURI) { .then(fileURI => {
fileURI.should.be.an.instanceOf(String); assert.ok(is.string(fileURI));
fileURI.should.startWith('https'); assert.equal(fileURI.indexOf('https'), 0);
done(); // TODO: validate URL with some library or regexp // TODO: validate URL with some library or regexp
}); });
}); });
}); });
describe('#downloadFile', function () { describe('#downloadFile', function downloadFileSuite() {
const downloadPath = __dirname;
var downloadPath = __dirname; it('should download a file', function test() {
const bot = new Telegram(TOKEN);
it('should download a file', function (done) { const photo = `${__dirname}/bot.gif`;
var bot = new Telegram(TOKEN);
var photo = __dirname + '/bot.gif';
// Send a file to get the ID // Send a file to get the ID
bot.sendPhoto(USERID, photo).then(function (resp) { return bot.sendPhoto(USERID, photo).then(resp => {
resp.should.be.an.instanceOf(Object); assert.ok(is.object(resp));
var fileId = resp.photo[0].file_id; const fileId = resp.photo[0].file_id;
bot.downloadFile(fileId, downloadPath) return bot
.then(function (filePath) { .downloadFile(fileId, downloadPath)
filePath.should.be.an.instanceOf(String); .then(filePath => {
fs.existsSync(filePath).should.be.true(); assert.ok(is.string(filePath));
assert.ok(fs.existsSync(filePath));
fs.unlinkSync(filePath); // Delete file after test fs.unlinkSync(filePath); // Delete file after test
done(); });
}); });
}); });
}); });
}); it('should call `onText` callback on match', function test(done) {
const bot = new Telegram(TOKEN, { webHook: true });
it('should call `onText` callback on match', function (done) { bot.onText(/\/echo (.+)/, (msg, match) => {
var bot = new Telegram(TOKEN, {webHook: true});
bot.onText(/\/echo (.+)/, function (msg, match) {
bot._WebHook._webServer.close(); bot._WebHook._webServer.close();
match[1].should.be.exactly('ECHO ALOHA'); assert.equal(match[1], 'ECHO ALOHA');
done(); done();
}); });
var url = 'http://localhost:8443/bot'+TOKEN; const url = `http://localhost:8443/bot${TOKEN}`;
request({ request({
url: url, url,
method: 'POST', method: 'POST',
json: true, json: true,
headers: { headers: {
'content-type': 'application/json', 'content-type': 'application/json',
}, },
body: {update_id: 0, message: {text: '/echo ECHO ALOHA'}} body: { update_id: 0, message: { text: '/echo ECHO ALOHA' } }
}); });
}); });
}); // End Telegram }); // End Telegram
describe('#TelegramBotPolling', function TelegramBotPollingSuite() {
describe('#TelegramBotPolling', function () { it('should call the callback on polling', function test(done) {
it('should call the callback on polling', function (done) { const opts = { interval: 100, timeout: 1 };
var opts = {interval: 100, timeout: 1}; const polling = new TelegramPolling(TOKEN, opts, (msg) => {
var polling = new TelegramPolling(TOKEN, opts, function (msg) {
if (msg.update_id === 10) { if (msg.update_id === 10) {
done(); done();
} }
}); });
// The second time _getUpdates is called it will return a message // The second time _getUpdates is called it will return a message
// Really dirty but it works // Really dirty but it works
polling._getUpdates = function () { polling._getUpdates = () => {
return new Promise.resolve([{update_id: 10, message: {}}]); return new Promise.resolve([{ update_id: 10, message: {} }]);
}; };
}); });
}); });

1
test/mocha.opts Normal file
View File

@ -0,0 +1 @@
--require babel-register