Build an Urban Dictionary Chatbot in PHP with Bref and the Twilio API for WhatsApp

September 24, 2020
Written by
Michael Okoko
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by
Diane Phan
Twilion

Build an Urban Dictionary Chatbot in PHP with Bref

Internet slang evolves so rapidly that it’s easy to get lost in communication while texting without the help of linguistic services like Urban Dictionary. Wouldn’t it be great if you could easily query new colloquialisms on the go?

In this tutorial, we will build a handy WhatsApp bot that gives us the Urban Dictionary definition of words. It will leverage the Twilio API for WhatsApp and the Urban Dictionary API to find and provide the definitions we need, on demand.

Prerequisites

In order to follow along with this tutorial, you will need the following:

Get Started

If you are using a UNIX or Mac OS system, create and enter into the project folder with the commands below:

$ mkdir urbandiction-bot && cd urbandiction-bot

For Windows developers, use the following commands in the command prompt window:

$ md urbandiction-bot
$ cd urbandiction-bot

Next, using Composer, install the dependencies the project will be needing:

$ composer require bref/bref twilio/sdk vlucas/phpdotenv bramus/router

Next, initialize a new Bref application in the project folder by running ./vendor/bin/bref init.

Select the [1] HTTP option from the interactive menu. That way, Bref understands that the project is meant to handle HTTP requests. It will also install support to easily provision AWS Lambda.

Screenshot of selecting Bref's HTTP option

The previous command creates an index.php file and a serverless.yml file in the project directory. The index.php file serves as your application entry point and will be modified later to additionally contain the application logic. The serverless.yml file contains the configuration needed for Bref to deploy your application to Lambda.

Set up your Twilio WhatsApp Sandbox

Though you will need an approved WhatsApp business account to use the API in production, Twilio provides an API sandbox for use while developing your application.

To activate the sandbox, visit the WhatsApp Sandbox page on your Twilio console and accept the terms of service. Upon activation, a unique combination of phone number and code will be generated for you.

Use your WhatsApp enabled device to send the unique code (i.e “join <YOUR-SANDBOX-CODE>”) as a WhatsApp message to your Sandbox number to start using it.

Whatsapp Sandbox Activation Screen

NOTE: If you get stuck, here is a detailed guide on getting up and running with the Twilio API for WhatsApp Sandbox.

Update your Environment Variables

Create a .env file in the project directory and add the Sandbox number from the previous section to it. Similarly, grab your Account SID and your Auth Token from your Console Dashboard and add them to the .env file as well as follows:

TWILIO_ACCOUNT_SID=<YOUR-TWILIO-ACCOUNT-SID>
TWILIO_AUTH_TOKEN=<YOUR-TWILIO-AUTH-TOKEN>
TWILIO_WHATSAPP_NUMBER=<"YOUR-TWILIO-SANDBOX-NUMBER">

Listen for New Messages

Open the index.php file in your code editor and replace its content with the code below:

<?php

require __DIR__ . '/vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$router = new \Bramus\Router\Router();

$router->post(
        "receive-message", function () {
            // the Body parameter contains the message body sent to us from WhatsApp
            $term = $_REQUEST['Body'];
            // the From variable is similar to "whatsapp%3A%2B2349074919559"
            $sender = $_REQUEST['From'];

            $response = getDefinitionsFor($term);
            $definitions = json_decode($response);
            if (count($definitions->list) > 1) {
                $top = $definitions->list[0];
                $message = $top->definition;
                $message .= "\n\n";
                $message .= "See https://www.urbandictionary.com/define.php?term=";
                $message .= urlencode($term);

            } else {
                $message = "No definition was found for ".$term;
            }

            sendMessage($message, $sender);

            header("Content-type", "application/json");
            echo json_encode(["status" => "OK"]);
            exit(0);
        }
);

$router->run();

The code above makes all of the credentials declared in the .env file available for our application to use with the help of  the phpdotenv package.

Next, the router is instantiated and a callable function is set up to handle the receive-message route. The function receives an incoming message and the Body value, which represents the word the user wants to search for. The From value is also received, which is the user’s phone number. A query is then executed in search of the definitions of the word and a $message variable is built whose value depends on whether or not a definition was found. The resulting $message is then sent back to the user.

Retrieve Definitions with PHP and cURL

The getDefinitionsFor function handles our app communication with the Urban Dictionary API using cURL. The function also returns any response it gets back to its caller.

Add the implementation for the getDefinitionsFor function below the receive-message handler, which is right before the $router->run(); line.

function getDefinitionsFor($term)
{
        $options = [
            CURLOPT_URL => "http://api.urbandictionary.com/v0/define?term=".$term,
            CURLOPT_RETURNTRANSFER => true
        ];
        $handle = curl_init();
        curl_setopt_array($handle, $options);
        $response = curl_exec($handle);
        curl_close($handle);
    
        return $response;
}

Send WhatsApp Messages

The sendMessage function uses the credentials declared in the .env file and asks Twilio to send a message to the recipient on our behalf.

In order for the sendMessage function to work, copy and paste the following code into the index.php file right below the function definition for getDefinitionsFor:

function sendMessage($message, $recipient)
{
        $sid = $_ENV["TWILIO_ACCOUNT_SID"];
        $token = $_ENV["TWILIO_AUTH_TOKEN"];
        $twilio = new \Twilio\Rest\Client($sid, $token);
        $twilio->messages->create(
            $recipient, [
                "from" => "whatsapp:".$_ENV["TWILIO_WHATSAPP_NUMBER"],
                "body" => $message
            ]
        );

        return;
}

The recipient is the sender variable we retrieved in the route handler. As a result of that, the phone number is formatted properly already. Remember to use the E.164 format of phone numbers if you are passing them in from a different source.

Expose your localhost with ngrok

Start the built-in PHP server and expose it to the internet with ngrok using the commands below. Feel free to use a different port if 3500 is not convenient.

Type the following commands in your terminal:

$ php -S localhost:3500
$ ngrok http 3500

The ngrok command will give you a list of URLs to interact with your locally-hosted application. Note the https version of the ngrok Forwarding URL, as we will be needing it shortly.

Head over to the WhatsApp Sandbox page on your Twilio console. Paste the ngrok Forwarding URL into the new message webhook field in the “A NEW MESSAGE COMES IN” field and click Save.

NOTE: Restarting ngrok will generate a new forwarding URL, so remember to update it again on your Twilio console if it changes.

Testing

Now you’re ready to test the application!

Message your Sandbox number with a word and you should get back the definition as seen on Urban Dictionary.

Screenshot of Urban Dictionary definitions

Deploy the project

Though we’ve used Bref PHP to bootstrap the project, you can deploy the code to your favorite PHP web host or cloud provider by copying the contents of the project folder to your server’s webroot.

You can also deploy it to AWS Lambda via the Serverless framework that Bref uses. In that case, the Bref documentation is a good place to get you started. You can also lookup the deployment sections in other recently posted Bref articles such as Forwarding Twilio Application Errors to Slack and Verifying Phone Numbers using Bref PHP.

Conclusion

By combining the Urban Dictionary API and the Twilio API for WhatsApp, we have found a way to easily stay updated with the newest internet slang. You can make further improvements like improving the conversation flow with AI using Twilio Autopilot.

The complete source code for the project is available if you want to check it out on GitLab.

Michael Okoko is a software engineer and computer science student at Obafemi Awolowo University, Nigeria. He loves open source and is mostly interested in Linux, Golang, PHP, and fantasy novels! You can reach him via: