Build a COVID-19 Data Tracker WhatsApp Chatbot using Twilio API for WhatsApp, PHP, and Symfony

June 10, 2020
Written by
Oluyemi Olususi
Contributor
Opinions expressed by Twilio contributors are their own

Build a COVID-19 Data Tracker WhatsApp Chatbot using Twilio API for WhatsApp, PHP, and Symfony

As the Coronavirus continues to exponentially spread across the globe, software developers around the world are doing the best they can to ensure the distribution of secured and trusted information concerning the Novel Coronavirus. For instance, numerous open-source API projects have been started to provide data to track the number of infected people, recovery rate, and unfortunately, the number of deaths recorded in different countries.

Commonly, to stay up-to-date with the statistics in your country or neighboring countries requires a browser and surfing the internet to get what is sometimes accurate information.

In this post, I will show you how to explore one of the recently published open-source APIs built to share the global data. During this process, we will build a WhatsApp chatbot that gives a summary of confirmed and recovered cases and the number of deaths recorded, respectively, by leveraging the infrastructure made available by the Twilio API for WhatsApp and Symfony.

Prerequisites 

To follow this tutorial, you will need the following:

Creating a new Symfony Application

To begin, we will use Composer to quickly create a new Symfony application. Alternatively, you can also use Symfony installer to set up your project by following the instructions here. To proceed, access the terminal in your operating system and navigate to your development directory. Then run the following command to create a project named symfony-covid19-tracker-bot.

$ composer create-project symfony/website-skeleton symfony-covid19-tracker-bot

The preceding command will install the new Symfony application on your computer. Once that has been completed, move into the folder for the newly created project and run the following command to install other dependencies:

// change directory
$ cd symfony-covid19-tracker-bot

// install other dependencies
$ composer require twilio/sdk nesbot/carbon symfony/web-server-bundle --dev ^4.4.2

The dependencies installed using the command above are:

  • twilio/sdk: A Twilio SDK for interacting with the Twilio API for WhatsApp
  • nesbot/carbon: A simple PHP API extension for Date and Time
  • symfony/web-server-bundle: A Symfony bundle to run a server locally.

Configure the Twilio WhatsApp Sandbox

Proceed to your Twilio dashboard and copy your Account SID and Auth Token. Record these credentials safely as we will need to use it for authenticating requests with the Twilio SDK:

Twilio Dashboard

Update Environment Variables

Open .env file and add the values of your ACCOUNT SID and AUTH TOKEN as obtained from your Twilio account dashboard:

TWILIO_ACCOUNT_SID=YOUR_ACCOUNT_SID
TWILIO_AUTH_TOKEN=YOUR_AUTH_TOKEN

Replace YOUR_ACCOUNT_SID and YOUR_AUTH_TOKEN with the appropriate values.

Setting up the Twilio Testing Sandbox

Similar to the conventional way of sending and receiving messages on WhatsApp, a number is always required. A provision has been made for you to have a WhatsApp approved Twilio number that can be used by the chatbot for subsequent conversations.

It usually takes days to get this number approved, which is why Twilio has also made a sandbox that has been pre-provisioned with a Twilio phone number for testing. With this sandbox, you can easily prototype with WhatsApp immediately pending Twilio number approval.

To use this Sandbox, proceed to the WhatsApp section on your Twilio dashboard and connect to the sandbox by sending a WhatsApp message from your device to the sandbox number provided; usually, +14155238886 with the provided code in this format “join {your sandbox keyword}”:

Sandbox Number

After successfully sending your code to the sandbox number, you will receive a confirmation indicating that your phone number has been added to the sandbox and can now send and receive messages:

Join sandbox

Update the .env file with the WhatsApp number as follows:

TWILIO_WHATSAPP_NUMBER="+14155238886"

We will return to update the sandbox later in the tutorial. Feel free to leave it open in a different tab. Next, we will start implementing the logic that will power the chatbot.

Create the WhatsApp ChatBot Controller

In this section, we will create a controller that will contain the business logic of our COVID-19 data tracker WhatsApp chatbot. Run the following command to use the SymfonyMakerBundle to automatically generate a CovidBotController class:

$ php bin/console make:controller CovidBotController

This will create two new files for you; a controller located in src/Controller/CovidBotController.php and a view page in templates/covid_bot/index.html.twig. We can ignore the view file for now.

Next, open the CovidBotController.php file and replace its content with:

// ./src/Controller/CovidBotController
<?php

namespace App\Controller;

use Carbon\Carbon;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Twilio\Rest\Client;

class CovidBotController extends AbstractController
{
    /**
     * @Route("/api/covid", name="covid_bot")
     */
    public function countryCasesSummary(Request $request)
    {
        $from = $request->request->get('From');
        $body = $request->request->get('Body');

        $httpClient = HttpClient::create();
        $response = $httpClient->request("GET", "https://covid19.mathdro.id/api/countries/$body");

        if ($response->getStatusCode() === 200) {
            $trackerResult = json_decode($response->getContent());

            $confirmed = $trackerResult->confirmed->value;
            $recovered = $trackerResult->recovered->value;
            $deaths = $trackerResult->deaths->value;
            $lastUpdate = Carbon::parse($trackerResult->lastUpdate)->diffForHumans();

            $message = "Here is the summary of the COVID-19 cases in " . '*'.$body.'*' . " as at " . $lastUpdate . "\n\n";
            $message .= "*Confirmed Cases:* $confirmed \n";
            $message .= "*Recovered Cases:* $recovered \n";
            $message .= "*Deaths Recorded:* $deaths \n";
            $message .= "*lastUpdate:* $lastUpdate \n";
            $this->postMessageToWhatsApp($message, $from);
            return new JsonResponse([
                'success' => true,
            ]);
        } else {
            $this->postMessageToWhatsApp("Country *$body* not found or doesn't have any cases", $from);
            return new JsonResponse([
                'success' => false,
            ]);
        }
    }
}

Whenever users send a message to our WhatsApp chatbot, Twilio will send a webhook - a user-defined HTTP callback - to our application. What we have defined above is the endpoint /api/covid to which Twilio’s request will be mapped to.

The countryCasesSummary() method will be responsible for handling the incoming messages and sending the appropriate responses back to the user. The Body of the HTTP request will represent the name of the country that a user wants to inquire about. This is in turn passed to the open-source API to return the COVID-19 cases details.

The functionality of sending the message to WhatsApp was abstracted to a helper function named postMessageToWhatsApp(). This method takes in two arguments:

  • $message: The summary of the COVID-19 cases as retrieved from the API and
  • $recipient:  The receiver of the details retrieved from the API, which in this case, will be the user interacting with our chatbot.

Define the postMessageToWhatsApp() method by updating the CovidBotController.php file with:

// ./src/Controller/CovidBotController
<?php

namespace App\Controller;

use Carbon\Carbon;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Twilio\Rest\Client;

class CovidBotController extends AbstractController
{
    ...

    public function postMessageToWhatsApp(string $message, string $recipient)
    {
        $twilio_whatsapp_number = getenv('TWILIO_WHATSAPP_NUMBER');
        $account_sid = getenv("TWILIO_ACCOUNT_SID");
        $auth_token = getenv("TWILIO_AUTH_TOKEN");

        $client = new Client($account_sid, $auth_token);
        return $client->messages->create($recipient, array('from' => "whatsapp:$twilio_whatsapp_number", 'body' => $message));
    }
}

First, your Twilio credentials stored in your .env file are retrieved before proceeding to create a new instance of the Twilio Client using your Account SID and Auth Token. Then, the recipient and an array of options are passed to the messages->create() method from the client instance to actually send out a request via the Twilio API. The messages->create() method takes in two arguments; the recipient, which is the WhatsApp enabled phone number you want to send a message to - in this case, the sender of the initial text - and an associative array with the keys: from and body. The from property should be your Twilio WhatsApp phone number or sandbox number (for testing only) with the text whatsapp: prepended to it, while the body property holds the $message to be sent to the recipient.

Running the Chatbot and Creating a Public URL

All is set now and we can proceed to run the application using the local web server. Use the following command for that purpose:

$ php bin/console server:run

This will start the application on your local server and it is available on port 8000. To make this accessible from the internet, we will make use of ngrok. This will provide a public URL for exposing our local server. If you haven’t, follow the instructions here to set it up on your computer. Once set up, run the following command from a new terminal:

$ ngrok http 8000

We used port 8000 because that is the default port for any Symfony application and where our application is currently running.

After successful execution of the command above, you should see a screen like this:

Ngrok result from terminal

Ngrok uses the Forwarding URL to redirect requests into our application. This will be appended with api/covid to form the URL for our webhook.

Updating the Sandbox Webhook

Go back to the WhatsApp sandbox settings in your Twilio dashboard and update the input field labeled "WHEN A MESSAGE COMES IN" with the complete URL to your chatbot path:

Click on Sandbox settings:

Twilio Sandbox

NOTE: Your webhook URL should be in the format https://{ngrok-forwarding-url}/api/covid

See It Working

Try out the chatbot by sending a WhatsApp message to it from your device. The message, in this case, should be the name of a particular country as depicted in the image below:

chat result

If it functions as expected, you will get a response with a summary of the COVID-19 cases in that country. If your input cannot be matched to a country in the API, a generic error message will be returned informing you that the country is either not found or has no cases.

Conclusion

In this tutorial, you have successfully built a WhatsApp chatbot with the ability to display the summary of COVID-19 cases in a particular country. This also provides an opportunity to learn how the Twilio API for WhatsApp works.

Find the complete source code here on GitHub.

Olususi Oluyemi is a tech enthusiast, programming freak, and a web development junkie who loves to embrace new technology.