3

I just want to download images received by my telegram bot with nodejs but I dont know witch method to use. I'm using node-telegram-bot-api and I tried this code :

bot.on('message', (msg) => {
    const img = bot.getFileLink(msg.photo[0].file_id);

    console.log(img);
});

That's the result:

Promise [Object] {
  _bitField: 0,
  _fulfillmentHandler0: undefined,
  _rejectionHandler0: undefined,
  _promise0: undefined,
  _receiver0: undefined,
  _cancellationParent:
   Promise [Object] {
     _bitField: 1,
     _fulfillmentHandler0: [Function],
     _rejectionHandler0: undefined,
     _promise0: [Circular],
     _receiver0: undefined,
     _cancellationParent:
      Promise [Object] {
        _bitField: 1,
        _fulfillmentHandler0: undefined,
        _rejectionHandler0: [Function],
        _promise0: [Circular],
        _receiver0: undefined,
        _cancellationParent: [Promise],
        _branchesRemainingToCancel: 1 },
     _branchesRemainingToCancel: 1 } }
baruchiro
  • 5,088
  • 5
  • 44
  • 66
sidikfaha
  • 139
  • 3
  • 12

4 Answers4

5
bot.on('message', async (msg) => {
    if (msg.photo && msg.photo[0]) {
        const image = await bot.getFile({ file_id: msg.photo[0].file_id });
        console.log(image);
    }
});

https://github.com/mast/telegram-bot-api/blob/master/lib/telegram-bot.js#L1407

Michael Rodriguez
  • 2,142
  • 1
  • 9
  • 15
4

There're three steps: An api request to get the "file directory" on Telegram. Use that "file directory" to create the "download URL". Use "request" module to download the file.

const fs = require('fs');
const request = require('request');
require('dotenv').config();
const path = require('path');
const fetch = require('node-fetch');

// this is used to download the file from the link
const download = (url, path, callback) => {
    request.head(url, (err, res, body) => {
    request(url).pipe(fs.createWriteStream(path)).on('close', callback);
  });
};
// handling incoming photo or any other file
bot.on('photo', async (doc) => {

    // there's other ways to get the file_id we just need it to get the download link
    const fileId = doc.update.message.photo[0].file_id;

    // an api request to get the "file directory" (file path)
    const res = await fetch(
      `https://api.telegram.org/bot${process.env.BOT_TOKEN}/getFile?file_id=${fileId}`
    );
    // extract the file path
    const res2 = await res.json();
    const filePath = res2.result.file_path;

    // now that we've "file path" we can generate the download link
    const downloadURL = 
      `https://api.telegram.org/file/bot${process.env.BOT_TOKEN}/${filePath}`;

    // download the file (in this case it's an image)
    download(downloadURL, path.join(__dirname, `${fileId}.jpg`), () =>
      console.log('Done!')
     );
});    

Links that may help: https://core.telegram.org/bots/api#file and https://core.telegram.org/bots/api#getfile

BEORN
  • 101
  • 5
1
  bot.getFile(msg.document.file_id).then((resp) => {
             console.log(resp)
         })
  • Please read [answer] and [edit] your answer to contain an explanation as to why this code would actually solve the problem at hand. Always remember that you're not only solving the problem, but are also educating the OP and any future readers of this post. – Adriaan Feb 22 '23 at 07:26
0

For node-telegram-bot-api should be :

const fileInfo= await bot.getFile(msg.photo[0].file_id);

Sample response :

{
  file_id: 'CgACAgQAAxkBAAIM_GLOjbnjU9mixP_6pdgpGOSgMQppAAIaAwAC0qkEUybVrAABHF2knCkE',
  file_unique_id: 'AgADGgMAAtKpBFM',
  file_size: 283369,
  file_path: 'animations/file_101.mp4'
}

or you can get download link by calling getFileLink :

const fileLink= await bot.getFile(msg.photo[0].file_id);

Result will be a string like :

https://api.telegram.org/file/bot11111111:AAGKlSEZSe_F0E6KouT2B5W77TmqpiQJtGQ/animations/file_101.mp4

or you can get download file using streams :

let fileWriter= fs.createWriteStream('myData.bin'); //creating stream for writing to file

//wrap to promise to use await as streams are not async/await based (they are based on events)
const getReadStreamPromise = () => {
        return new Promise((resolve, reject) => {
            const stream = bot.getFileStream(body.Message.FileId); //getting strean to file bytes
            stream.on('data', (chunk) => {
                console.log('getting data')
                fileWriter.write(chunk); //copying to our file chunk by chunk
            })
            stream.on('error', (err) => {
                console.log('err')
                reject(err);
            })
            stream.on('end', () => {
                console.log('end')
                resolve();
            })

        })
    }
    console.log('Start file downloading and saving');
    await getReadStreamPromise(); 
    console.log('File saved');

so your file will be saved to myData.bin file

Nigrimmist
  • 10,289
  • 4
  • 52
  • 53