From d9692f45a95e2bbc211b2297e4886084008b574a Mon Sep 17 00:00:00 2001 From: GochoMugo Date: Thu, 7 Dec 2017 12:04:46 +0300 Subject: [PATCH] src/telegram: Add TelegramBot#getFileStream() References: * FR: https://github.com/yagop/node-telegram-bot-api/issues/442 --- CHANGELOG.md | 2 ++ doc/api.md | 17 +++++++++++++++++ package.json | 1 + src/telegram.js | 22 ++++++++++++++++++++++ test/telegram.js | 26 ++++++++++++++++++++++---- 5 files changed, 64 insertions(+), 4 deletions(-) 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); }); });