Make a NFC tag catalyzed Telegram bot
Tags: nfc, bot, tutorial, node
Published: 2020-03-24 21:53:34

If you love automation like me, I think that you will find this very interesting.

In this step-by-step guide, we are going to make a bot that sends a specific message to a certain Telegram ID every time the phone is put next to a NFC tag.

## Intro

The system flow is quite simple:

The phone is put next to the NFC tag and a task runner app makes a GET request to a specific URL provided by Heroku where the Telegram bot lives. Once this URL is reached, the bot sends a specific message, that is passed as a query string, to a predetermined Telegram ID.

And that’s it. So, now you understand it, let's make that system!

This tutorial has two parts, the first is the fun one, the creation of the server; and the second one is the phone's set up. But if you don’t feel like going through the tutorial, I will drop [here](https://github.com/jmmzzei/nfc-telegram) the link to the repo.

Okay, let's start with the fun part.

## Bot Creation

I made the bot with Javascript, the runtime Node, the libraries Express, Helmet, Dotenv and Telegraf (a framework to make Telegram bots in Node.js) and Heroku to host it and make it publicly available.

I will start with the obvious, initialize the project in a repository.
```bash
    mkdir Telegram-NFC && cd $_ && npm init -y
```
Install the dependencies.

    npm i express telegraf helmet dotenv

Initialize git.

    git init

Create a .gitignore file with these two lines in it.
```bash
    echo “node_modules
    .env” > .gitignore
```
Create a `.env` file to store all the environment variables during development.
```bash
    echo “BOT_TOKEN=
    ID=
    PORT=3000” > .env
```
We are going to leave it like that and return to it later.

### Create `config.js`

At the root of the repo, create `config.js`
```bash
    touch config.js
```
and insert in it:
```javascript
    require('dotenv').config()
    module.exports = {
        bot_token : process.env.BOT_TOKEN,
        id: process.env.ID
        port : process.env.PORT,
    }
```
Here we took the environment variables and reassigned its value to a key inside an object that will be exported through the CommonJS module formatting system.

### Create index.js

At the root of the repo, create `index.js`
```bash
    touch index.js
```
and inside it, type:
```javascript
    const express = require(‘express’)
    const Telegraf = require (‘telegraf’)
    const {bot_token, port, id} = require(‘./config’) // import the variables from config
    const app = express() // create an Express app

    app.set(‘port’, process.env.PORT || port) // set a port to listen
    app.use(require(‘helmet’)()) // make use of the helmet library
    const bot = new Telegraf(bot_token) // create an instance of Telegraf
    bot.start((ctx) => ctx.reply('Welcome human!')) // start the bot
    
    //define an endpoint
    app.get(`/${bot_token}`, async (req, res) => { 
    if(req.query.message){
    try {
        await bot.telegram.sendMessage(id, req.query.message)
        res.send('Message Sended!')
    } catch (error) {    
        res.send(error)
    }
    } else {
        res.send(‘No message to send.’)
    }
    })
```
What I did in the last block of code was setting the endpoint for a GET HTTP method. Every time a request reaches this endpoint and if it presents a query string with a key equal to ‘message’, the server will try to send this message to the passed Telegram ID (this is the addressee) and will reply, on success or on error, with a message.

> Note: You could set your endpoint to the root of the URL but, for the sake of security, I recommend you use your private bot token in your path.

Finally, we will set our server to listen on a specific port.

```javascript
    app.listen(app.get(‘port’), () => {
    console.log(`Server listen on port ${app.get(‘port’)}`)
    })
```

Bonus: If you need to perform a specific function in response to an addressee reply, you probably should opt for setting a webhook. Telegraf provides a couple of methods to perform this.
```javascript
    app.use(bot.webhookCallback(`/${bot_token}`))
    bot.telegram.setWebhook(`<your-heroku-url>/${bot_token}`)
```
### Populate the `.env` file.

To fill the BOT_TOKEN key you need to get your bot token. In the first place, you must send some messages to the BotFather. In Telegram, look it up and type /start => /newbot => your-bot-name => a-username-for-your-bot (must end with ‘bot’). And this should reveal to you the token of your bot.

To fill the ID key of the `.env` file, you need to get the Telegram ID of your addressee. You could find a bot that delivers to you this data but, unfortunately, I can’t tell you any because I can’t really know which one is secure and which one is not.
Nevertheless, I can tell you how I got the ID. I created a little bot with the same tech stack used in this tutorial, that replies with the Telegram ID of the person who sends the message. Then I send a message from the addressee phone to this bot to get the info.

I know it's a bit tricky. If you have issues with this step, feel free to reach out to me and I will write another post explaining this part, or I can send you the script I used.

### Upload to Heroku

Heroku offers us different ways to deploy our app. I’m going to use the Heroku CLI because it's astonishingly simple.

- Create an account.

- Create a new app in the Heroku Dashboard.

- Download the Heroku CLI [here](https://devcenter.heroku.com/articles/heroku-cli).

Then you need to login through the Heroku CLI to create a new SSH public key.

    heroku login

Add the Heroku repo as your remote.

    heroku git:remote -a <your-heroku-app-name>

And finally, in the terminal...

    git add .
    git commit
    git push heroku master

One final step, remember that we didn't commit the `.env` file so we need to set the environment variables somewhere. To do that, in Heroku, we need to go to Dashboard/your-app/Settings and Config Vars. Once there, adding the necessary variables should be a piece of cake. The variables that you should add are the same that you have in your `.env`, except for the port.

> Note: Since we are making use of the free version, Heroku will put your bot to sleep after 30 minutes of inactivity. So if the bot takes from 5 to 10 seconds to send the message and the response, that's okay, Heroku needs approximately that time to wake up your bot.

And that’s it. The bot you have created is now deployed and running in the cloud.

## Setting up the phone

In this part you need to install and set up a couple of apps on your phone. I will explain the steps for Android, which is the OS I use, but I don’t think that exists many differences if you have an iPhone.

Let’s begin.

Once you have installed in your phone the NFC Tools and NFC Tasks apps, you need to open NFC Tools and go to write/registry/URL and type https://your-app-name.herokuapp.com/your-bot-token/?message=your-message. Then place the NFC tag next to your phone and write the data to your tag.

And that's pretty much all you need to do. The next time you put your phone next to the tag, the NFC Task will open your predefined browser with the specified URL in the address bar. Then, the browser will make a GET request to that URL and trigger a series of steps that will end with the bot sending the message, passed as a query string in the URL, to the addressee.

> Note: In order to receive messages from the bot, the addressee has to explicitly start it.

That's all! As you may see, the server took us a few lines to create and set up the phone didn't take us too long. Nevertheless, simplicity doesn’t mean futility. In fact, you could add different endpoints and different tags to expand its functionality. I would love to know the variations you make to the project.

I hope you liked this guide and had a good time creating the bot.
For any recommendation or comment, feel free to reach out to me or leave a comment below. You could also report an issue on the [Github repo](https://github.com/jmmzzei/nfc-telegram).

Thanks!