How to Make a Password Generator Bot - Part 1 [Typescript/Telegraf.js]
Tags: typescript, tutorial, node, programming
Published: 2023-06-11 08:50:52

**Hi again DEV!**

Welcome to _part one_ of a _nine-part_ series on creating a simple password generator Telegram bot! In this series, we will build a fully functional bot that generates secure passwords for Telegram users in 9 different programming languages.

If you want more context or a simple introduction, read up on the [previous post](https://dev.to/kidesleo/making-a-password-generator-bot-in-9-languages-30fn) of this series. You can also find the source code [here](https://github.com/KidesLeo/9-Languages-1-Bot). I will also try my best to answer any questions below!

I’m a full-stack web developer, which means that no matter how agnostic I am towards programming languages, I cannot escape JavaScript/TypeScript. And that is why we’ll start our first bot off in Typescript.

Let’s start by going through a checklist of what we’ll need. 
1. Installed [NodeJS Runtime](https://nodejs.org/en/download)
2. [NPM](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) or [Yarn](https://classic.yarnpkg.com/lang/en/docs/install)

That’s it? Yes. For now, at least. Once we have a NodeJS 
runtime installed, we can instantiate our Typescript project. 

## Setting Up

```javascript
npm init
# or
yarn init
```
When prompted, set your entry point to “index.ts”. You can leave everything else blank.

Once set up, we can install all the dependencies for our little project.

We will use [dotenv](https://github.com/motdotla/dotenv) to import and use .env files and [Telegraf.js](https://github.com/telegraf/telegraf/) to massively simplify the development process. We will also use [tsx](https://github.com/esbuild-kit/tsx) to run our typescript files.

```javascript
npm install dotenv telegraf tsx @types/node
```
Or if you're using yarn
```javascript
yarn add dotenv telegraf tsx @types/node
```

_Tip #1.1_: In the `package.json` file, add the following.
```json
"scripts": {
        "dev": "tsx watch index.ts"
    },
```

The `scripts` key lets you add custom scripts to your NodeJS project, and in this case, the `dev` script will run tsx with the watch argument. This will ensure that NodeJS will automatically restart every time `index.ts` is altered.

If you do not have a telegram bot token, please refer to the previous post for instructions on acquiring a new bot token. You can also follow [this official](https://core.telegram.org/bots/tutorial#obtain-your-bot-token) step-by-step guide.

Once we have everything installed, create a file labeled `.env`, and write into it the following: 

```javascript
BOT_TOKEN=
```

Make sure to append your bot token after the equals sign, we will be reading from it later. It should look something like this

```javascript
BOT_TOKEN=4839574812:AAFD39kkdpWt3ywyRZergyOLMaJhac60qc
```

[dotenv](https://github.com/motdotla/dotenv) enables developers to load environment variables from a .env file into the process environment. The .env file contains key-value pairs of configuration variables, allowing developers to store sensitive information like API keys, database credentials, or other configuration values securely in a separate file. Since our bot token is of the utmost importance, this is one secure way of storing and accessing it.

## Let’s start coding!

Now that everything is set up, let’s create a new file called `index.ts` and open it in a code editor.

Let’s start by importing our dependencies.

```javascript
import { Telegraf } from "telegraf";
import * as dotenv from "dotenv";
```

We will then move on to creating our string generation function. 

This function, named `generateString`, will receive a length parameter for the length of the generated string and return a random string containing various characters from a given character set.

```javascript
// String generation function
function generateString(length: number) {
    const KeyString =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-=";
    let RandString = "";
    for (let i = 0; i < length; i++) {
        /* We randomly select a character 
        from the key and add it RandString*/
        RandString += KeyString.charAt(
            Math.floor(Math.random() * KeyString.length)
        );
    }
    // Remove characters to fit the markdown rule
    return (
        "||" + RandString.replace(/[~!@#$%^&*()-_=+{}\|;:',.?]/g, "\\$&") + "||"
    );
}
```

As explained in [Part #0](https://dev.to/kidesleo/making-a-password-generator-bot-in-9-languages-30fn), when a user prompts for a new password, we randomly select a character from the key string a given number of times and concatenate the characters into a new variable, which we then return. 

I added one more thing to this function, right at the end. We have to escape all the symbols in the password so that we don’t accidentally apply markdown styles in our using our generated string and that’s just what the [`replace` Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace) function does. 

You might also wonder what the “||” symbols are for. As per the Telegram [documentation](https://core.telegram.org/bots/update56kabdkb12ibuisabdubodbasbdaosd#markdownv2-style), those are the symbols used for spoiler text.

With our handy function implemented, it's time to initialize our telegram bot. Using the next snippet we run the default `dotenv` configuration and import the bot token from the process environment.
 
Telegram accepts a bot token to create a bot instance.

```javascript
dotenv.config();
const token = process.env.BOT_TOKEN || "";
const bot = new Telegraf(token);
```

Let’s then launch our bot and add a simple print to show that the bot has started. 

_NOTE: This bot will be polling to receive information from the telegram API, if you want to look at the webhook implementation, check out the [Telegraf.js documentation/repo](https://github.com/telegraf/telegraf/)._

```javascript
bot.launch();
console.log("Running bot...");
```

## Starting /start

Adding a start command is pretty straightforward thanks to [Telegraf.js](https://github.com/telegraf/telegraf/).
 
```javascript
// Start command code
bot.start(async (ctx) =>
    ctx.reply(
        "Press /generate to get a newly generated password. You can also send a number to receive a password of that length."
    )
);
```

The `bot.start` function will be invoked every time the start command is called. The function passes the [context](https://telegraf.js.org/classes/Context.html), and using the context we can reply to the user with initial instructions on using our bot.

## Time to /generate

[Telegraf.js](https://github.com/telegraf/telegraf/) provides a handy way of describing command functions with `bot.command`. Similar to `bot.start`, the `.command` callback is run every time a command matching the specified string is sent.

When it comes to our password generation command, we have to prepare for two scenarios. With and without a length parameter.
 
If there is no parameter, we respond with a 12-character password. 

If it is specified, all we do is pass that on to the generateString function. Since telegram has a character limit of 4096, we don’t have to worry about a max length.
All we have to do is check for the number of spaces and we can easily deduce the number of arguments, like so.

```javascript
// Generate command code
bot.command("generate", async (ctx) => {
    const MessageArr = ctx.update.message.text.split(" ");
    if (MessageArr.length == 2) {
        return await ctx.replyWithMarkdownV2(
            generateString(Number(MessageArr[1])),
            {
                parse_mode: "MarkdownV2",
            }
        );
    } else if (MessageArr.length > 2)
        return ctx.reply("Incorrect amount of arguments, try /help");
    return await ctx.replyWithMarkdownV2(generateString(12), {
        parse_mode: "MarkdownV2",
    });
});
```

So maybe that got a little hairy. Let’s break it down.
We first create `MessageArr` to store every string that is separated by a “ “. This variable is a convenient array and we can use it to determine if there are any arguments sent with the command.

If we have only the command and one argument, we pass in that argument and return a string. If there is only the command, we generate a 12-character string and return that instead. 

If we have an incorrect number of arguments, we recommend to the user the `/help` command. 

The `.replyWithMarkdownV2` function is a [Telegraf.js](https://github.com/telegraf/telegraf/) function that lets us pass markdown text in a way that Telegram understands them. 

## /help! The article is ending!

Last and kind of least, we have the `/help` command. Keeping it simple, here is the code for that.

```javascript
// Help command code
bot.command(
    "help",
    async (ctx) =>
        await ctx.replyWithMarkdownV2(
            "Use the /generate command to create an AlphaNumeric 12-character password\\. \nYou can also provide an argument to set the length of the password, " +
                "for example, `/generate 15` to generate a string of 15 character\\.",
            { parse_mode: "MarkdownV2" }
        )
);
```

Having flavored it up a bit with Markdown, the help text is ready to go.

Well, let’s run it then.

```javascript
yarn dev
```

Your console should display only the following

```javascript
Running bot...
```

Try texting your bot on Telegram and everything should be working perfectly.

## Debugging

If you are experiencing confusing console errors and various other issues, feel free to ask down below, I will try my best to respond to everyone.

If you see `Running bot…` in your console but you’re getting no responses from your bot, try adding a print in the code blocks for each command to pinpoint the problem. Again, feel free to ask for help down below.

## Closing Credits

_1 done_, **8** to go. *Thanks for reading DEV!*

If you have any questions, suggestions, or tips, please feel free to comment below. I will respond as quickly as I can.

I truly hope you enjoyed reading all of that and gained something from it. Hopefully both, but either is good. 

In case you are curious about this series and whatever else I’ll be up to more stuff like this, drop a follow and a like, it’s much appreciated!