Build a WhatsApp Chatbot Voting Application Using NodeJs and Twilio
Tags: twilio, node, bot, whatsappbot
Published: 2023-03-16 14:07:32


## Build a WhatsApp Chatbot Voting Application Using NodeJs and Twilio

With the rate of technological advancement taking place in this century, we are always finding new ways to automate our tasks and make our lives better. Chatbots help us reduce our dependence on our manual ways of communication and also challenges our preconceived way of implementing solutions.

## What is a ChatBot?

In its mere definition, it is a software application used to conduct an online chat conversation via text or text-to-speech, in place of providing direct contact with a live human agent. It has been used in different contexts ranging from customer support, book tickets for movie/show, banking(UBA Leo) just to mention a few. Its use can only be limited by our creativity!

In this tutorial, we would be embarking on a creativity journey by building a voting WhatsApp Chatbot with NodeJs using the Twilio Platform.

After successfully following this tutorial, you would have learned how to:

 1. respond to WhatsApp messages sent to your Twilio WhatsApp number

 2. develop a Rest API based voting application

 3. send free-form messages using the Twilio WhatsApp API

## Prerequisites

To successfully follow through with this tutorial the following are required:

* Basic knowledge of NodeJs

* NodeJs and Npm installed on your machine

* A WhatsApp enabled Twilio number

* Twilio Account

* An installation of [ngrok](https://ngrok.com/product)

## Setup and Installation

We would make use of Nodejs. Start by creating a directory, then cd into it and run this command

    $ mkdir e-voting && cd e-voting

Then we initialize a node project by creating a package.json, the command allows the creation of the file without us entering prompt values. You can later change the values in this file.

    $ npm init -y 

Next, we proceed to install the packages we would be using

    $ npm i express twilio

Express — We use to set up our server

Twilio — The Twilio Library we would use to send messages

Now that we have our environment set up, let's proceed to our Twilio [sandbox](https://www.twilio.com/console/sms/whatsapp/learn) to set things up.

## Setting up the WhatsApp Sandbox

In other to give our chatbot access to the messages from WhatsApp, Twilio provides a very robust [WhatsApp API](https://www.twilio.com/whatsapp) that allows us to both send and receive WhatsApp messages right from within our application.

However before we can start sending and receiving messages using the Twilio WhatsApp API in production, we must first get a [WhatsApp Approved Twilio Number](https://www.twilio.com/whatsapp/request-access) which will act as our WhatsApp number for sending and receiving messages. For this tutorial we would not involve ourselves in that process, we would rather leverage on a safe [sandbox](https://www.twilio.com/console/sms/whatsapp/learn) Twilio provides for development and testing purposes.

To begin using the Twilio WhatsApp Sandbox, we proceed to the [WhatsApp section](https://www.twilio.com/console/sms/whatsapp/learn) on the Twilio dashboard and send a message to the sandbox number provided; usually, +14155238886 with the provided code, which is in the format join-{unique word}:

![](https://cdn-images-1.medium.com/max/2732/1*lqGb0hDYQmc6sJ18Ltxbbw.png)

You should receive a response similar to the one below once you join. If you didn't check the process you followed to make sure you didn't miss any step.

![](https://cdn-images-1.medium.com/max/2000/1*XslwAxlsILNzK5EeXYWl_g.jpeg)

## Building the App

From the installation, we have only a package.json file in our project. We would then create a new file called index.js which would be used to set up our application server(with expressjs)
{% gist https://gist.github.com/chyke007/6a1e2381b9ece09de048c889658811a7.js %}
The above simply uses express to spin up a server and uses a route file which was imported on line 2. We would later send all request to our server on the **/vote** route which points to this external route file.

Next, we proceed to create a routes.js which would hold the logic
{% gist https://gist.github.com/chyke007/350f47645d42133ee737285325e58d5d.js %}
I know this file looks quite a lot but with some explanation, you would see it's not that complex. To make the explanation easier I would be explaining section by section.

The **First Section** spans from Line1–5 is where we install helpers files and methods into our application. At Line 3, we installed the Twilio official NodeJs module which we would use to send back our response. Line 4 we imported our helper response module(this would help format our various responses). Line 5, sees us introduce our utility module where we store our helper functions.

The **Second Section** spans from Line 7–25 is where we define our file variables and default values, like votes and candidates.

The **Third Section** spans from Line 27–43 and only consists of one function, showCandidates, we simply use this to show our list of candidates once requested by the user.

The **Fourth Section** spans from Line 46–136 and consists of four functions which are in charge of actually accepting and validating users vote and showing the result to the user. The first two functions are the actual voting while the last two are for showing results. Here is how it works:

**a) castVote**(): It begins the voting process and also takes users vote. Once a user chooses to vote and this method is called for the first time through Line 218, it creates a tracker for that particular user in the server through Line 82, after it has performed a check to ascertain that there are candidates to be voted for(Line 81).

It then returns a response with the list of candidates with their id to enable the user to know how to vote for their chosen candidate in their next chat, it also includes a way to cancel the voting process and remove the tracker from the user end by appending the unique value(0) which should be used by the user to opt-out of the voting process (Line 83 which calls list_of_candidate accepts showCandidates function as a parameter).

When the user responds next with a chat, we then check by converting the chat value to a Number and check its value, if it's a 0, we know the user wants to cancel the voting process(Line 203), we then cancel the process and send a response to the user that we have. If the user rather sends any other value we then call **castVote** with the required parameters(Line 207).

When castVote is called and passed these values we then go to line 75 where we make sure the user hasn't voted before, then we proceed to Line 76 to recheck that the user has indeed begun the process of voting and lastly we proceed to confirm that there are actually candidates to be voted for in Line 77. After this, we call **addVote** in Line 78 with the provided parameters.

b) **addVote**(): This function is charged with the actual reception of users vote. Firstly we check at Line 58 to make sure that the value supplied by the user actually is an id of a Candidate. We then proceed to add that users vote, remove them from the voting process and send back a successful response (Line 61-63).

c) **showResult()**: We use this function to show the result to users. Line 118–119 is simply used to validate and make sure that votes and candidates exist respectively. At line 121 we group all votes by the candidate. Then at Line 122, we format the response we get from Line 121 in such a way we can show the user the name of each candidate, the total votes they amassed and their percentage of votes. Also, we show a winner or draw where applicable(the formatResult function at Line 95 helps us with this formatting and result response.

d)**formatResponse**(): Like said above, found at Line 95, it simply gets the grouped votes by their candidates, then it returns the names of each candidate, their votes count and percentage of votes. It also checks for a draw or winner and returns this formatted result as its response.

The **Fifth Section** spans from Line 139–191 and consists of display and default message and a footer which we include for every response. **showDefaultMessage**() is used at the beginning to show a list of actions that can be performed. **showHelp**() ****shows the help menu whenever it's called while the **footer** includes an additional message to all response.

The **Sixth and Last Section** which spans from Line 191–243 is where we accept the post request made to the server, parse the body content, process the user input and send a response. Line 197 simply gives us the user phone number, this is the unique identifier for each user. We use the switch statements to get users response and call the corresponding function.

That's basically what this file does, it serves as the engine of our chatbot.

Next, let's add the utility.js file that would hold our helper files
{% gist https://gist.github.com/chyke007/cf12721036b6f786ac78aa0313b4e3a8.js %}
We have just 4 methods here that basically help us to perform various manipulations of data.

We also include our responses.js file
{% gist https://gist.github.com/chyke007/9f9bdd5ba8e306b12ad750713147a174.js %}
Now that we are done with the coding section, your project structure should look something like this:

![Project Structure](https://cdn-images-1.medium.com/max/2000/1*tiHvp9SGtQzO2Fjt2pDUlg.png)

We then have a functional server, we would now proceed to create a webhook that would allow us to redirect requests.

## Create a Webhook

This allows Twilio API to be able to send the request to our application endpoint. This is where ngrok.io.

If you don't have [ngrok](https://ngrok.com), proceed [here](https://ngrok.com/download) to see how to get and set it up to run in your system. We are going to use the URL provided by ngrok as our webhook URL.

But before we do that we need to start our server, let's open a terminal at the root of our project and run:

    node index.js

This would spin up our server and expose it to a port. In our case, that port is 4000.

Next, we open a different terminal and run

    ngrok http 4000

You should then see this on your terminal, Ngrok doing its job!

![Port Forwarding with Ngrok](https://cdn-images-1.medium.com/max/2000/1*e58LnG_4YYFIGIsaPnIpPg.png)

Though not needed we could go to the Web Interface URL(http://127.0.0.1:4040) provided in the image to see requests as they are made to the endpoints:

![Request Dashboard](https://cdn-images-1.medium.com/max/2488/1*6npkjXJXfa4bJ9GmygQlmA.png)

Now update the webhook in Twilio to point to the exposed URL provided by Ngrok. This would redirect all messages from Twilio to our nodeJs server running locally on our system. Head over here and input the URL obtained from Ngrok and append it with /vote as this is our full endpoint. Then update the input field labelled “WHEN A MESSAGE COMES IN” with this value.

For our case, we would input [http://9905d7076291.ngrok.io/vote](http://9905d7076291.ngrok.io/vote)

![Twilio Sandbox Configuration](https://cdn-images-1.medium.com/max/2552/1*RUTF0M1q19YYvmJdb76f0w.png)

## Testing

Now that we have set up our webhook, let’s test it out on WhatsApp. A Hi message responds with the default message we supplied in our code. We can see that working properly:

![](https://cdn-images-1.medium.com/max/2000/1*Ky4eqycF_lnfuGB_GtZJhg.png)

And when we send 3 to the bot, we get polling results back, it works!:

![Shows Result](https://cdn-images-1.medium.com/max/2000/1*ai3YH7IVqS_77Tf_OspMeg.png)

## Demo

The Live demo can be found [here](https://www.youtube.com/watch?v=xls_7abY27I). I went further to add more features to the project, the complete project with admin functionality and features can be found [here](https://github.com/chyke007/e-voting).

## Conclusion

A major reason why I love this voting application is that it allows me to partake in a voting process without having to leave my best messaging platform.

Technological advances have enabled us to live out our imaginations which we would have never thought possible in the previous century. I have just lived out one of mine! I can’t wait to see what you build!