Get a Word of the Day SMS with Python and Twilio

August 12, 2020
Written by
Mridu Bhatnagar
Contributor
Opinions expressed by Twilio contributors are their own

Get a Word of the Day SMS with Python and Twilio

Due to the current Coronavirus situation all of us are doing more work online. For effective collaboration, good written communication skills have become the need of the hour. Taking this into account I decided to build a service that sends a new word, along with its definition, each day as an SMS notification.

This tutorial will show you how to create a service that sends you a new word every day using the Twilio Programmable Messaging APIs, Python and Heroku. Below you can see the notifications that come on my smart phone each day.

word of the day demo

Tutorial Requirements

To follow this you need the following components:

Create a Python Virtual Environment

Let us start by creating the directory where our project will live. Inside your terminal enter:

$ mkdir word-notifier
$ cd word-notifier

Following best practices we are going to create a virtual environment where we will install our Python dependencies.

If you are using a UNIX or MacOS system, open a terminal and enter the following commands to do the tasks mentioned above.

$ python3 -m venv word-notifier-venv
$ source word-notifier-venv/bin/activate
(word-notifier-venv) $ pip install twilio requests python-dotenv 

For those of you following the tutorial on Windows, enter the following commands in a command prompt window:

$ python -m venv word-notifier-venv
$ word-notifier-venv\scripts\activate
(word-notifier-venv) $ pip install twilio requests python-dotenv

In the command above, venv is a Python module that creates virtual environments. The word-notifier-venv argument is the name of the virtual environment we created. The last command uses pip, the Python package installer, to install the packages that we are going to use in this project, which are:

For your reference, at the time this tutorial was released these were the versions of the above packages and their dependencies tested:

certifi==2020.6.20
chardet==3.0.4
idna==2.10
PyJWT==1.7.1
python-dotenv==0.14.0
pytz==2020.1
requests==2.24.0
six==1.15.0
twilio==6.44.2
urllib3==1.25.10

Next we are going to write the list of packages and dependencies installed in the virtual environment to a requirements.txt file, as we will need this later in the tutorial. To do this, run the following command:

(word-notifier-venv) $ pip freeze > requirements.txt

Configuring Twilio Programmable Messaging

This is where we make sure you have a Twilio phone number activated. Log onto the Twilio Console to view your Active Numbers. Click on the number you want to use to view the details. If you haven’t purchased a number yet, learn how to search for and buy a Twilio phone number. Note that if you are using a trial account you will be using your Twilio trial credits for this purchase.

Twilio phone numbers

We’ll now create a .env file (note the leading dot) to save the secret credentials and other configuration options. Add the following variables to your .env file. These are going to be used by our application to be able to authenticate and send SMS.

TWILIO_ACCOUNT_SID=<your Twilio Account SID>
TWILIO_AUTH_TOKEN=<your Twilio Auth Token>
TWILIO_PHONE_NUMBER=<your purchased Twilio phone number>
RECEIVER_PHONE_NUMBER=<your own phone number>

For the TWILIO_ACCOUNT_SID and  TWILIO_AUTH_TOKEN variables, you can obtain the values that apply to your account from the Twilio Console.

Twilio Account SID and Auth Token

The TWILIO_PHONE_NUMBER variable must be set to the Twilio number that you purchased. This is going to be the number that is sending the SMS. The RECEIVER_PHONE_NUMBER variable should be set to the number on which you want to receive the SMS notifications. Both phone numbers need to be given in the E.164 format.

Setting up the Wordnik API

To get a word of the day we will use the Wordnik API, for which we require an API access key. Follow the steps below to get the API key.

1. Sign Up on the Wordnik platform. After signing up, you’ll receive an email from Wordnik to verify your account.

Create Wordnik account

2. Once the account is verified, log in to request the Wordnik API key. On the Wordnik dashboard, click on your username and select the settings option from the dropdown as shown in the image below.

Wordnik settings

3. Go to the bottom of the settings page. Just below “Wordnik API Key” there is a link to the developers page, where you can request a key.

Wordnik settings page

4. On the developer page there is a sign up form. You need to submit the sign up form, and you’ll receive the API keys through email in up to a few days. Don’t worry about the delay in getting the key, you’ll be able to complete this project using a fake word of the day while you wait for your key.

Request Wordnik API key

If you already have the Wordnik API key, you can add it to your .env file:

WORDNIK_API_KEY=<your wordnik API key>

If you are waiting to receive the key, you can leave this variable set to an empty value until you receive it:

WORDNIK_API_KEY=

Create the Python web service

The Word Notifier application we are going to build is split into 2 functions:

  • get_word_of_the_day - helps in querying the data source and fetching a new word every day based on the current date.
  • send_sms - helps in communicating with the Twilio Programmable Messaging API to   deliver an SMS to the receiver’s phone.

In the following sections we’ll develop the application.

Importing the dependencies

Create a new file app.py inside of your project directory with the following code that imports all our dependencies:

import os
import json
from datetime import date
import requests
from dotenv import load_dotenv
from twilio.rest import Client

Imports in the code snippet:

  • os - Part of the Python standard library. We’ll use it to read environment variables.
  • json - Part of the Python standard library. We’ll use it to convert JSON data to a Python dictionary.
  • date - Part of the Python standard library. We’ll use it to get the current date.
  • requests - A Python HTTP client library. We’ll use it to query the Wordnik API and get the word of the day.  
  • load_dotenv - This function imports all the variables stored in the .env file into the environment.
  • twilio.rest.Client - This is the Twilio Client library to access the Twilio Programmable SMS API.

Reading environment variables

Next we are going to read all the environment variables that we stored in the .env file. Add the following code at the bottom of app.py:

load_dotenv()

TWILIO_ACCOUNT_SID = os.getenv("TWILIO_ACCOUNT_SID")
TWILIO_AUTH_TOKEN = os.getenv("TWILIO_AUTH_TOKEN")
TWILIO_PHONE_NUMBER = os.getenv("TWILIO_PHONE_NUMBER")
RECEIVER_PHONE_NUMBER = os.getenv("RECEIVER_PHONE_NUMBER")
WORDNIK_API_KEY = os.getenv("WORDNIK_API_KEY")

The load_dotenv() function imports the contents of the .env file into the environment, and the os.getenv() function then reads individual variables from the environment. We assign each environment variable to a variable of the same name in the application.

Getting the Word of the Day

Following the Wordnik documentation, to get the word of the day we have to send a request to the https://api.wordnik.com/v4/words.json/wordOfTheDay URL with two parameters given in the query string:

  • date is the requested day, given in the format YYYY-MM-DD
  • api_key is the Wordnik API key.

Below you can see the implementation of the first of our two functions, get_word_of_the_day. Add this code at the bottom of app.py.

def get_word_of_the_day(current_date):
    """
    Fetch word of the day from the Wordnik API
    """
    response_data = {"word": "Sorry, No new word today", "definition": "No definition available"}
    if WORDNIK_API_KEY:
        url = f"https://api.wordnik.com/v4/words.json/wordOfTheDay?date={current_date}" \
              f"&api_key={WORDNIK_API_KEY}"
        response = requests.get(url)
        api_response = json.loads(response.text)
        if response.status_code == 200:
            response_data["word"] = api_response["word"]
            for definition in api_response["definitions"]:
                response_data["definition"] = definition["text"]
                break
    else:
        # use a mock word if there is no Wordnik API key
        response_data["word"] = "mesmerizing"
        response_data["definition"] = "capturing one's attention as if by magic"
    return response_data

If the Wordnik API key is an empty string we use a mock word and word definition. If the API key is present, then we send a GET request to the API. If the API call is successful we update the default values of word and definition in the response_data dictionary.

The Wordnik API response includes a word key, which contains the word of the day. The response includes a list of definitions for this word in a list from different sources. We are using only the first definition.

Below is the example usage of this function from a Python shell:

>> from datetime import date
>> from app import get_word_of_the_day
>> current_date = date.today()
>> get_word_of_the_day(current_date)
{'word': 'zaitech', 'definition': 'Application of financial engineering techniques in Japanese financial markets since their deregulation in 1984.'}

Sending messages with Twilio

The primary aim of writing this web service is to be able to send SMS notifications with a new word and its definition every day to your smartphone.

In the next code snippet we will authenticate the Twilio client and define the function send_sms. Add this function at the end of app.py.

def send_sms(response_data):
    """
    Send SMS notification with New word
    """
    client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
    body = response_data["word"] + "\n\n" + response_data["definition"]
    message = client.messages.create(
        body=body,
        from_=TWILIO_PHONE_NUMBER,
        to=RECEIVER_PHONE_NUMBER
    )

Notes on the send_sms function:

1. We authenticate the Client object using the TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN.

2. The body variable contains the new word along with its definition, formatted as a string.

3. Using the client.messages.create function we create the message that will be delivered. The body, from_ and to arguments define the message, the sender and the recipient respectively.

Now that our two functions are implemented we can invoke them one after another to obtain the word of the day and send the SMS with it. Add the following code at the bottom of app.py to make these calls:

if __name__ == "__main__":
    current_date = date.today()
    data = get_word_of_the_day(current_date)
    send_sms(data)

Everything together

Now, we have seen all aspects of the implementation. Let us integrate all the pieces and create the complete web service. If you haven’t built the application yet, you can copy the code below to the app.py file. You can also use the code listing as a reference if you have been building the application incrementally.

import os
import json
from datetime import date
import requests
from dotenv import load_dotenv
from twilio.rest import Client

load_dotenv()

TWILIO_ACCOUNT_SID = os.getenv("TWILIO_ACCOUNT_SID")
TWILIO_AUTH_TOKEN = os.getenv("TWILIO_AUTH_TOKEN")
TWILIO_PHONE_NUMBER = os.getenv("TWILIO_PHONE_NUMBER")
RECEIVER_PHONE_NUMBER = os.getenv("RECEIVER_PHONE_NUMBER")
WORDNIK_API_KEY = os.getenv("WORDNIK_API_KEY")


def get_word_of_the_day(current_date):
    """
    Fetch word of the day from the Wordnik API
    """
    response_data = {"word": "Sorry, No new word today", "definition": "No definition available"}
    if WORDNIK_API_KEY:
        url = f"https://api.wordnik.com/v4/words.json/wordOfTheDay?date={current_date}" \
              f"&api_key={WORDNIK_API_KEY}"
        response = requests.get(url)
        api_response = json.loads(response.text)
        if response.status_code == 200:
            response_data["word"] = api_response["word"]
            for definition in api_response["definitions"]:
                response_data["definition"] = definition["text"]
                break
    else:
        # use a mock word if there is no Wordnik API key
        response_data["word"] = "mesmerizing"
        response_data["definition"] = "capturing one's attention as if by magic"
    return response_data


def send_sms(response_data):
    """
    Send SMS notification with New word
    """
    client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
    body = response_data["word"] + "\n\n" + response_data["definition"]
    message = client.messages.create(
        body=body,
        from_=TWILIO_PHONE_NUMBER,
        to=RECEIVER_PHONE_NUMBER
    )


if __name__ == "__main__":
    current_date = date.today()
    data = get_word_of_the_day(current_date)
    send_sms(data)

Running the application

To start the application, run the following command from the terminal:

python app.py

After the application finishes, check your smartphone. You should receive a SMS notification with the word of the day and its definition. Note that if you are running the application while you are waiting to receive your API key from Wordnik, then you will always get the same word. Once you receive the key you can add it to your `.env` file to start getting real words.

Schedule the application to run daily

In this final part of the tutorial we are going to deploy the application to Heroku and configure it to run automatically every day.

Create a local Git repository

Make sure you have git configured on your terminal. You can follow these steps to configure git. Then run the following command to initialize your working directory to a local git repository:

git init

Next, you can add your project files and commit the changes to git.

git add app.py requirements.txt 
git commit -m "word notifier source code"

Deploying the application on Heroku

We’ll be now deploying and scheduling our web service on Heroku. Create a free account on the Heroku web site, and then setup the Heroku CLI by following the steps mentioned in the official documentation.

Create an application on Heroku by running the following command on the terminal:

heroku create word-notifier

Note that you may need to pick a different name than word-notifier, as the application names have to be unique. When you create the app, a git remote (called Heroku) is also created and associated with your local git repository.

Now deploy your code to Heroku by pushing your code to this remote:

git push heroku master

Finally, we need to define the environment variables that we have in our .env file so that they are also available on Heroku. Go to your Heroku application dashboard, select the application and then click on “Settings”. Then click on “Reveal Config Vars”.

Add the five environment variables that you have defined in the .env file:

heroku dashboard
 

You can now test the deployment. Run the application using the command below:

heroku run python app.py

When the application finishes you’ll receive the SMS notification on your mobile phone.

Scheduling the web service on Heroku

We are now going to schedule the deployed application so that it runs everyday at a given time.

Install the Heroku Scheduler add-on. Note that even though this add-on is offered for free, Heroku requires the account to be verified by entering credit card details before you can install it. Once installed, the scheduler add-on will be visible in your app dashboard, under the “Resources” tab.

heroku scheduler

To schedule the web service to run every day click on “Heroku Scheduler” under “Resources”. You can set a time according to your preference in the scheduler dashboard.

heroku scheduler configuration

Once the time is set, the application will run according to this schedule, and each time it runs an SMS with the current word of the day will be delivered to your phone.

word of the day demo

 

 

Conclusion

In this tutorial, we have created a Python web service that sends a Word of the Day SMS notification each day at the scheduled time. This was implemented using Python and Twilio API for Programmable Messaging. The service is deployed and scheduled on Heroku. The data for fetching a new “Word of the Day” and its definition was fetched from the Wordnik API. The GitHub repository with the complete source code can be found here.

Mridu Bhatnagar

Blogs: https://dev.to/mridubhatnagar
Github: https://github.com/mridubhatnagar
Twitter: https://twitter.com/Mridu__