About
Photos

On Telegram bot development

Why

As you may have noticed, I like taking pictures. I also like looking at others pics and encouraging people to make and share them.

Since I'm somewhat active in the Nerdsbay community, I have decided to create a telegram channel for people to share their photos. No discussions, just photos.

But immediately, there is a problem - how do I let people send their images to the channel - obviously, I'd like to be able to either approve or reject those pics.

Let's start

So, we need a public channel, a private group where people will be able to approve images and a bot which will forward messages from the user to that group and then to the channel.

To create a bot, you have to interact with the bot father - this is pretty straight-forward and I'm gonna skip it here.

We'll be using node.js, let's start with adding a couple of packages we'll need.

npm install node-telegram-bot-api
npm install locallydb

The 1st one is the api that we're going to use to interact with the bot, the 2nd - a rather dumb "database".

The api works pretty much like a web socket - it starts polling and lets you to subscribe to some events. First of all, we need a "photo" event.


const bot = new TelegramBot(token, { polling: true });

bot.on('photo', (msg) => {});
            

All the files are stored by telegram separately, so we don't actually need to download it - only memorize it's "file_unique_id". Let's save it to the collection:


chatsArray.insert({
  user: msg.chat.id,
  fileId: msg.photo[0].file_unique_id,
  msgId: msg.message_id,
});

We're going to need the id of this chat to be able to respond to the user, who sent the picture.

Now we need to forward this message to the admin group, this is pretty straightforward as well.

bot.forwardMessage(groupID, msg.chat.id, msg.message_id);

Next, the bot needs to react to the message in that group and forward the message to the channel and additionally notify the original sender that their picture has been approved (or not).

This is why we have saved the user id into the array - in sone cases, a user can hide their username on forwarded messages - the only way t trace the user back is by the file uniq id .


bot.onText(/ok\s?(.*)/, (msg, match) => {
  const comment = match[1]; // the captured "comment"
  bot.forwardMessage(channelID, msg.chat.id, msg.reply_to_message.message_id); // forwarding to the channel
  const savedUser = getUserByFile(fileId);
  bot.sendMessage(
    savedUser.user,
    'we have approved your photo',
    {
      reply_to_message_id: savedUser.msgId,
    },
  );
  ...
const getUserByFile = (fileId) => {
  const list = chatsArray.where({ fileId });
  if (list.length() === 0) {
    return null;
  }

  return list.items[0];
};
        

Here the bot reacts to a message that matches the regexp (i.e. messages like "ok we like it") if this message came as a reply to the photo in the group.

Additionally, you may want to check that this reply is indeed in the group or have some approved users list.

That's it

You may see this code here: on Github.

Wait, how do I run it?

The good thing is that you don't need any domain or even a static IP to host this bot backend. But if you're unhappy with running it on your machine, there's a great option.

You can obtain an Oracle free tier virtual machine. On which you can install any OS you like.

After trying several options to run my little node script and detach it from the ssh terminal, I've found out that forever works nest for me.

So, install it and run your script:

npm install -g forever && forever start ./app.js

Done

In case you'd need a telegram bot for something, you now know how to start!