diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1cb0391..8882d00 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,8 @@ Added:
* (#440) *TelegramBot#setChatStickerSet*, *TelegramBot#deleteChatStickerSet* (by @kamikazechaser)
1. Support Bot API v3.5:
* Support `provider_data` parameter in *TelegramBot#sendInvoice* (by @GochoMugo)
+1. Add methods:
+ * *TelegramBot#getFileStream* (#442) (by @GochoMugo, requested-by @Xaqron)
1. Add options to *TelegramBot#stopPolling()* (by @GochoMugo)
1. Add `metadata` argument in `message` event (and
friends e.g. `text`, `audio`, etc.) (#409) (by @jlsjonas, @GochoMugo)
diff --git a/doc/api.md b/doc/api.md
index f5ae4d2..641f11a 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -61,6 +61,7 @@ TelegramBot
* [.sendContact(chatId, phoneNumber, firstName, [options])](#TelegramBot+sendContact) ⇒ Promise
* [.getFile(fileId, [options])](#TelegramBot+getFile) ⇒ Promise
* [.getFileLink(fileId, [options])](#TelegramBot+getFileLink) ⇒ Promise
+ * [.getFileStream(fileId, [options])](#TelegramBot+getFileStream) ⇒ stream.Readable
* [.downloadFile(fileId, downloadDir, [options])](#TelegramBot+downloadFile) ⇒ Promise
* [.onText(regexp, callback)](#TelegramBot+onText)
* [.removeTextListener(regexp)](#TelegramBot+removeTextListener) ⇒ Object
@@ -841,6 +842,22 @@ which returns just path to file on remote server (you will have to manually buil
| fileId | String
| File identifier to get info about |
| [options] | Object
| Additional Telegram query options |
+
+
+### telegramBot.getFileStream(fileId, [options]) ⇒ stream.Readable
+Return a readable stream for file.
+
+This method is a sugar extension of the [getFileLink](#TelegramBot+getFileLink) method,
+which returns the full URI to the file on remote server.
+
+**Kind**: instance method of [TelegramBot](#TelegramBot)
+**Returns**: stream.Readable
- stream
+
+| Param | Type | Description |
+| --- | --- | --- |
+| fileId | String
| File identifier to get info about |
+| [options] | Object
| Additional Telegram query options |
+
### telegramBot.downloadFile(fileId, downloadDir, [options]) ⇒ Promise
diff --git a/package.json b/package.json
index dcd12ad..3e66174 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"babel-plugin-transform-strict-mode": "^6.6.5",
"babel-preset-es2015": "^6.6.0",
"babel-register": "^6.7.2",
+ "concat-stream": "^1.6.0",
"contributor": "^0.1.25",
"eslint": "^2.13.1",
"eslint-config-airbnb": "^6.2.0",
diff --git a/src/telegram.js b/src/telegram.js
index df94cd8..73c293b 100644
--- a/src/telegram.js
+++ b/src/telegram.js
@@ -1322,6 +1322,28 @@ class TelegramBot extends EventEmitter {
.then(resp => `${this.options.baseApiUrl}/file/bot${this.token}/${resp.file_path}`);
}
+ /**
+ * Return a readable stream for file.
+ *
+ * This method is a sugar extension of the [getFileLink](#TelegramBot+getFileLink) method,
+ * which returns the full URI to the file on remote server.
+ *
+ * @param {String} fileId File identifier to get info about
+ * @param {Object} [options] Additional Telegram query options
+ * @return {stream.Readable} stream
+ */
+ getFileStream(fileId, form = {}) {
+ const fileStream = new stream.PassThrough();
+ this.getFileLink(fileId, form)
+ .then((fileURI) => {
+ pump(streamedRequest({ uri: fileURI }), fileStream);
+ })
+ .catch((error) => {
+ fileStream.emit('error', error);
+ });
+ return fileStream;
+ }
+
/**
* Downloads file in the specified folder.
* This is just a sugar for (getFile)[#getfilefiled] method
diff --git a/test/telegram.js b/test/telegram.js
index b300ab2..c23b3bf 100644
--- a/test/telegram.js
+++ b/test/telegram.js
@@ -5,9 +5,11 @@ const assert = require('assert');
const fs = require('fs');
const os = require('os');
const path = require('path');
+const stream = require('stream');
const is = require('is');
const utils = require('./utils');
const isCI = require('is-ci');
+const concat = require('concat-stream');
// Allows self-signed certificates to be used in our tests
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
@@ -41,6 +43,7 @@ const ip = '216.58.210.174'; // Google IP ¯\_(ツ)_/¯
const cert = `${__dirname}/../examples/crt.pem`;
const lat = 47.5351072;
const long = -52.7508537;
+const FILE_PATH = `${__dirname}/data/photo.gif`;
let FILE_ID;
let GAME_CHAT_ID;
let GAME_MSG_ID;
@@ -101,7 +104,7 @@ describe('TelegramBot', function telegramSuite() {
utils.handleRatelimit(bot, 'sendPhoto', this);
utils.handleRatelimit(bot, 'sendMessage', this);
utils.handleRatelimit(bot, 'sendGame', this);
- return bot.sendPhoto(USERID, `${__dirname}/data/photo.gif`).then(resp => {
+ return bot.sendPhoto(USERID, FILE_PATH).then(resp => {
FILE_ID = resp.photo[0].file_id;
return bot.sendMessage(USERID, 'chat');
}).then(resp => {
@@ -1162,6 +1165,21 @@ describe('TelegramBot', function telegramSuite() {
});
});
+ describe('#getFileStream', function getFileStreamSuite() {
+ this.timeout(timeout);
+ before(function before() {
+ // utils.handleRatelimit(bot, 'getFileStream', this);
+ });
+ it('should get a file stream', function test(done) {
+ const fileStream = bot.getFileStream(FILE_ID);
+ assert.ok(fileStream instanceof stream.Readable);
+ fileStream.pipe(concat(function readFile(buffer) {
+ buffer.equals(fs.readFileSync(FILE_PATH)); // sync :(
+ return done();
+ }));
+ });
+ });
+
describe('#downloadFile', function downloadFileSuite() {
const downloadPath = os.tmpdir();
this.timeout(timeout);
@@ -1362,9 +1380,9 @@ describe('TelegramBot', function telegramSuite() {
});
});
it('should allow stream.path that can not be parsed', function test() {
- const stream = fs.createReadStream(`${__dirname}/data/photo.gif`);
- stream.path = '/?id=123'; // for example, 'http://example.com/?id=666'
- return bot.sendPhoto(USERID, stream);
+ const fileStream = fs.createReadStream(`${__dirname}/data/photo.gif`);
+ fileStream.path = '/?id=123'; // for example, 'http://example.com/?id=666'
+ return bot.sendPhoto(USERID, fileStream);
});
});