Been a while since I have posted here!

Happy New Year!!!

Happy New Year!!

This post will be short and sweet where I quickly made a Telegram Captcha bot. I will work on this and make it more effecient in the future.

Requirements

  1. Node.js (Express.js)
  2. Telegram Bot (Created in Botfater)

Let’s Begin!

Firstly I used the Express Skeleton generator to generate a skeleton structure of a Node.js server (you can also just create a normal Node.js server, I use the generator daily and this is a force of habit).

Create a blank folder and enter npx express-generator in your command terminal and immediatly npm install to install the dependecies.

For this project we will use 2 NPM packages:

  1. Node Telegram Bot API
  2. Captcha Generator (This will generate our captcha text and images.)

Install both npm packages with your terminal:

npm i node-telegram-bot-api
npm i @haileybot/captcha-generator

Setup Telegram in Node

We will include the package and create a Telegram Bot client:

const TelegramBot = require('node-telegram-bot-api');
const token = config.telegram.token;
const bot = new TelegramBot(token, {
  polling: true
});

Generate our Captcha

We will now generate our captcha by creating a new captcha object (this is handle by the captcha generator package):

let captcha = new Captcha();

From our captcha object we want the generated value and image. We can retrieve it by calling the dataURL and value functions.

let image = captcha.dataURL;
let correctValue = captcha.value;

Telegram Answer Buttons

We would like to send the correct answer with 4 different incorrect answers for the user. We will send the answers with inline Telegram buttons where the user can simply press on one instead of having to type out the answer. To achieve this we need to generate 4 different answers and push all of them with the correct answer into an array:

let arrValues = [];
arrValues.push(correctValue);

for (i = 0; i < 4; i++) {
    arrValues.push(makeid(6));
}

You might have notice the makeid(6) function. This is not a JS function and we need to write our own function to generate our random string. We loop 4 time to generate 4 string and all of them need to be 6 characters long. The makeid function will look as follow:

function makeid(length) {
  var result = '';
  var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  var charactersLength = characters.length;
  for (var i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}

After we have our correct answer and 4 strings, we need to shuffle the array to make sure that the correct answer will appear randomly when it sends to the user. To achieve this we will write our own shuffle() function:

function shuffle(array) {
  var currentIndex = array.length,
    temporaryValue, randomIndex;

  while (0 !== currentIndex) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

Our shuffle function is based on the Fisher-Yates (aka Knuth) Shuffle algorithm.

Now we would like to add our button to an array of objects that we will attach to our inline keyboard. We simply loop through our array and create an object for each button and push it into the array.

let arrButtons = [];
let obj;
for (i = 0; i < 5; i++) {
    obj = {};
    obj['text'] = arrValues[i];
    obj['callback_data'] = arrValues[i];
    arrButtons.push(obj);
}

We simply add the aaray to the Telegram keyboard and send it with a custom message:

const opts = {
    reply_markup: {
    inline_keyboard: [
        arrButtons
    ]}
}
bot.sendMessage(msg.chat.id, "Please choose the correct text on the photo:", opts);

Captcha Image

We won’t get far without out captcha image because then the user won’t have anything to compare the buttons to.

We simply take the image data url and convert it to a buffer:

var regex = /^data:.+\/(.+);base64,(.*)$/;

var matches = string.match(regex);
var ext = matches[1];
var data = matches[2];
var buffer = Buffer.from(data, 'base64');

Lastly we send the photo to the user:

bot.sendPhoto(msg.chat.id, buffer);

Below are screenshots of how the program runs: Send Picture and 5 Different Answers

Below is an example of a successful captcha selection: Passed Captcha

Below is an example of a failed captcha selection: Failed Captcha

If you would like to see the whole set of code, it is available on my GitHub page.