Build a WhatsApp Synonyms Game Bot with Python, Flask and Twilio
Time to read: 10 minutes
A research from 2013 shows that games can increase learning outcomes by two grade levels. The effect of games on learning can never be over-emphasized. So wouldn’t it be a good idea to build a word game to learn more about a language? I think it will be fun. Building the game on WhatsApp, an application with over 2 billion users around the globe, makes it even more interesting!
In this tutorial, I am going to do a walkthrough on how to build your own word game on WhatsApp. For the purpose of this tutorial, the word game will be centered around synonyms. The game will present you with words, and you will need to enter synonyms. Each time you enter a correct synonym you earn a point. The game continues until you make a mistake, at which you point your score is given to you. A generic approach will be adopted in order to make this extensible to other word games (antonyms, etc.) that you may want to build in the future.
Prerequisites
If you wish to follow along with the tutorial, you will need to have the following components:
- A Twilio account. Create one if you don’t have it yet. This is important for the Twilio phone number which will be used to implement the game.
- A Merriam-Webster's developer account. Create one if you don’t have it yet. An API key will be provided on sign-up.
- A mobile phone with WhatsApp installed to test the game.
- Python 3.6 or newer. Download the Python installer for your operating system here.
- ngrok. Since Twilio needs to connect to a public URL, we will be using ngrok (a free tool) to put our web app running on our local machine temporarily on the Internet. Download the ngrok installer for your operating system here.
Set up Twilio WhatsApp sandbox
Twilio provides a WhatsApp sandbox to enable easy development and testing of our applications. To connect to the sandbox from your smartphone, select Programmable Messaging from your Twilio Console, click “Try it Out” and finally Try WhatsApp. The WhatsApp sandbox page shows the sandbox number assigned to your account, and a join code as shown below:
To enable the WhatsApp sandbox for your smartphone, you need to send a WhatsApp message with the given code (which begins with the word join, followed by a randomly generated two-word phrase) to the number assigned to your account. Twilio responds with confirmation that your mobile number is connected to the sandbox after it receives the code. This step needs to be repeated for any additional phones you’d like to have connected to your sandbox. Also, note that sandbox sessions expire after 3 days and you will need to send the code again to the number in order to get reconnected.
Create a Python virtual environment
It’s best practice to create separate virtual environments for different python projects. With that in mind, we should create one for our game. To start with, we will make a new directory for our project, and create the virtual environment inside it. Then we will activate the virtual environment and install the following packages needed for our game:
- The Flask framework, to create the web application
- The Twilio Python Helper library, to work with the Twilio APIs
- The Requests package, to access the WordsAPI
For Windows users following along, enter the following commands in a command prompt window to complete these tasks:
If you are on a Unix or Mac OS system, enter the following commands on a terminal window:
For reference purposes, below you can see the versions of the installed packages and their dependencies that were used to successfully develop and test the game. Here is a link to a requirements.txt file on GitHub with the same content.
Getting started with the Merriam-Webster API
By now you should have created a Merriam-Webster developer account, and should have gotten a key for the Collegiate Thesaurus API. Below is a screenshot of the API keys page:
The picture below shows the available APIs from Merriam-Webster and highlighted in red the place where you would see the API key that we will be using for our application.
The overview for this API is located here. In particular this page shows the request URL to access the API:
Next, I am going to show some examples of how to work with the endpoint from the command prompt with Python. If you want to follow along, make sure that your Python virtual environment is activated.
Then add your Merriam-Webster API key as an environment variable. For Windows users:
For Unix or Mac OS users:
Type python3
in your command prompt or terminal window to start a Python interactive session. You should see the Python version information followed by the >>>
Python prompt:
Now, I would show how to work with the API from the python terminal.
We started the Python session by importing os
and requests
. We will use os
to retrieve the API key environment variable, and requests
to make HTTP requests to the Merriam-Webster API.
We then set the word “synonym” as an example first word, and then create a url
variable with the request URL, including the desired word and the API key, and following the guidelines in the API documentation.
Next we send a GET
request to the endpoint URL we just created. This is done by calling the requests.get()
function and passing the URL as an argument. The requests package returns a response object, which we capture in the response
variable.
The response.json()
method returns the JSON data returned by the API as a Python dictionary. From there we need to filter the data and only keep the synonyms, which is what we are interested in. This is done with the expression response.json()[0]['meta']['syns'][0]
.
In the second half of the session we repeat the process using the word “immortal”.
Generating random words
In the example session from the previous section we manually selected words to be searched for. We obviously want to automate this process and have the game select random words on its own. To do this we are going to use a JSON file containing about 1000 common English words. The JSON file can be found in this GitHub repository and here is the raw file. Thanks to Darius Kazemi who has made this repository available.
From a Python session we can grab this word list as follows:
Once we have the list of words, we can select one at random using Python’s random
module:
The Twilio API for WhatsApp
The Twilio API for WhatsApp uses a webhook to notify an application when there is an incoming message. For our game application, we need to define an endpoint that is going to be configured as this webhook so that Twilio can communicate with our application. For this purpose, we would be using the Flask framework which makes it easy to define a webhook.
If you are not familiar with the Flask framework, its documentation has a quick start section that should bring you up to speed quickly. If you want a more in-depth learning resource then I recommend you follow Miguel Grinberg’s Flask Mega-Tutorial.
Below you can see the standard format to define a webhook for an application:
The above code defines a /synonymsgame
endpoint that supports POST
requests. The body of the function bot()
will contain the logic to process the incoming message and return a response.
The first thing that needs to be done in our game application is to obtain the message entered by the user on WhatsApp. This message comes in the payload of the POST
request with a key of ’Body’
and can be accessed through Flask’s request
object:
The message received is stripped of any whitespace and converted to lowercase to ensure that we don’t have to worry about all the different ways a word can appear when you introduce case variations.
The response that Twilio expects from the webhook needs to be given in TwiML or Twilio Markup Language, which is an XML-based language. However, the Twilio helper library for Python comes with classes that make it easy to create this response without having to create XML directly. Below you can see the code necessary to create a response that includes text that will be shown to the user on WhatsApp:
Creating the Game
This section will bring all the details we have covered in the previous sections together. That is, now we will be implementing the actual logic for the game.
Basic endpoint structure
Below you can see the beginning of synonymsgame.py, where we import all the dependencies and define the Flask endpoint:
First, we make the necessary imports, and create our app
application instance. Flask applications require a secret_key
definition to work with session objects, so we define it by getting the value from the environment variable with the name SECRET_KEY
. The api_key
variable has been discussed earlier, this is the developer key to access the Merriam-Webster API, and is also imported from an environment variable.
Next we define the webhook and the starter code for the game logic, which gets the message from the user and defines a message response object that we will use to return messages to the user.
Handling new games
Continuing with the logic in the bot()
function, now we can check if a new game is starting. This happens when the user writes “new game” in WhatsApp.
To initialize a new game we obtain a new random word and its synonyms. We do not have a get_word()
function yet, but we’ll write it soon.
Since we need to remember the state of the game as we interact with the user on WhatsApp, we store a number of things in the session
variable from Flask:
num_correct
, which represents the number of correct answers, initially set to 0.random_word
, the selected random word.synonyms
, the synonyms of the selected random word
We finally generate a message to the user telling them what the word is.
Handling ongoing games
If the endpoint is invoked in the middle of a game, we can retrieve the game state from the variables we stored in the session
object. The following code continues with the body of the bot()
function and handles an answer from the user.
Here we restore the random word and synonyms from the user session, and then check if the word typed by the user on WhatsApp is in our list of synonyms.
If the word is a valid synonym, then we increment the num_correct
variable in the session, replace the word and its synonyms with a new randomly generated word, and inform the user what the next word is.
If the word entered by the user is not in our list, then the game is over. In that case we clean up the session and return a final message to the user with the score.
The big if statement that controls the game logic has a third and final section, which applies when the user did not type “new game” and we do not have the session variables that indicate that we have a game in progress. In that case we just let the user know what the command to start a new game is.
At the very end of the function we return the resp
object, in which we have created our response to the user.
Generating random words
The game logic we wrote in the previous section uses the get_word()
auxiliary function. This function chooses a random word from the list of common words in JSON format, and then obtains its synonyms from the Merriam-Webster API. The function returns the word and its synonyms in a tuple.
Below you can see the definition of the function. Add it at the end of the synonymsgame.py file:
Starting the web server
The final piece of our application is the lines that run the Flask server. These go at the bottom of the synonymsgame.py file:
Everything Together
Now you have seen all the aspects of the chatbot implementation, so we are ready to integrate all the pieces into the complete chatbot service. If you haven’t been building the application along, you can now copy the complete code shown below into the synonymsgame.py file:
Testing the Game
Final lap! Before you start the game make sure that you have defined the two environment variables that the game needs. As a reminder, their names are SECRET_KEY
and API_KEY
. On a Windows machine, you can set them as follows:
If you use a Unix or Mac OS computer, then use the following commands:
The value that you choose for the SECRET_KEY
variable can be anything you like. Flask will use this to generate a cryptographic signature for the user sessions, making them secure.
After copying the code from the previous section into the *synonymsgame.py* file, you can start the game by running python synonymsgame.py
and making sure you do this while the Python virtual environment is activated and the environment variables are set. The output should be something like this:
The service is now running as a private service on port 5000 inside your computer and will sit there waiting for incoming connections.
As discussed earlier, we are going to use ngrok to make the application reachable by Twilio over the Internet. Open a second terminal window and run ngrok http 5000
to allocate a temporary public domain that redirects HTTP requests to our local port 5000. The output of ngrok is:
Note the two lines that start with “Forwarding”. These show the http:// and https:// URLs that are temporarily mapped to the application running locally.
The final step is to tell Twilio to use this URL to send incoming message notifications. To achieve this, go back to the Twilio Console, click on Programmable Messaging, then on Settings, and finally on WhatsApp Sandbox Settings. Copy the https:// URL from the ngrok output and then paste it on the “When a message comes in” field. Since our chatbot is exposed under the /synonymsgame
URL, append that at the end of the root ngrok URL. Make sure the request method is set to HTTP Post
and don’t forget to click the Save button at the bottom of the page to record these changes.
Now you can start playing the game from the smartphone that you connected to the sandbox. Send new game to the sandbox number to begin!
Conclusion
Games provide a 23% gain over traditional learning. A word game like this can be useful in learning new words to improve our vocabulary. Also, this can be useful to prepare for exams requiring verbal reasoning such as the GRE® General Test.
I hope this tutorial was useful and you now have a better idea of how to build and extend a word game for WhatsApp. I would love to see you build some more interesting word games. If you want to learn more about the Twilio API for WhatsApp, here is a link to the documentation.
Ayoyinka Obisesan is a Graduate student at Carnegie Mellon University Africa.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.