How to Keep Friends Accountable Using Twilio Programmable SMS, Python, and Flask
Time to read: 11 minutes
It’s no mystery that the transition to online learning or working from home has impacted all of our lives. If you’re like me, you miss going out to a local coffee shop and being productive without distractions. It’s also nice to study and work with others around you to motivate you and keep you from checking social media every minute.
Completing this tutorial will allow you to host a system for you and your friends to be able to change your status throughout the day, everyday. Plus, you’ll realize just how easy it is to get started with coding!
In this post, I’ll show you how to develop a functional Python program to organize your work groups using Twilio Programmable SMS and Flask.
Tutorial Requirements
In order to build this project, you will need to have the following items ready:
- Python 3.6 or newer. If your operating system does not provide a Python interpreter, you can go to python.org to download an installer.
- ngrok. We will use this handy utility to connect the development version of our Python application running on your system to a public URL that Twilio can connect to. This is necessary for the development version of the application because your computer is likely behind a router or firewall, so it isn’t directly reachable on the Internet. If you don’t have ngrok installed, you can download a copy for Windows, MacOS or Linux.
- A free or paid Twilio account. If you are new to Twilio get your free account now! (If you sign up through this link will give you $10 credit when you upgrade.)
Configuration
We’ll start off by creating a directory to store our project files. Inside your favorite terminal, enter:
Since we will be installing some Python packages for this specific project, we need to create a virtual environment.
If you are using a Unix or MacOS system, open a terminal and enter the following commands:
NOTE: Depending on what version of Python you are on, you might have to specify python3
.
If you are on a Windows machine, enter the following commands in a prompt window:
If you are curious to learn more about the packages, you can check them out here:
- The Flask framework, to create the web application that will receive message notifications from Twilio
- The python-dotenv package, to load the environment variables created
- The python-twilio package, to send messages through the Twilio service
Configure Twilio SMS
This is where we make sure you have a Twilio phone number activated. Log onto the Twilio Dashboard
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.
Authenticate against Twilio Service
Next, we need to create a .env file to safely store some important credentials that will be used to authenticate against the Twilio service. We’re going to set this up now but we’ll discuss more about it in the section “Keep each other accountable”.
Here is what the .env file should look like:
For the TWILIO_ACCOUNT_SID
and TWILIO_AUTH_TOKEN
variables, you can obtain the values that apply to your Twilio account from the Twilio Console:
Use the following functions to import your .env variables. You can add this code under the lines that import all of your packages:
Receive and send messages with Twilio
The goal of our app is to allow friends to text your Twilio number and add themselves to the Work Accountability Directory. Your friends will be able to set their statuses by sending in a text message from their devices at any time in order to update the directory for other users to see.
Receive messages
The Twilio API for Programmable SMS uses a webhook (web callback) to allow real-time data to be delivered to other applications. This is especially important since we want to constantly be able to view our friends’ statuses.
Here’s some code to help you write your first webhook handler. Create a file named accountability.py and import the following packages and code:
We have a few things going on with the code above. The @app.route
is a decorator from our Flask framework, which helps get API projects started quickly. This decorator will work with our webhook()
function that will be included in a URL so that we can receive incoming messages from any user.
The student
variable receives a value from Flask’s request.form
function. When we look at the From
parameter, Flask is able to parse the phone number of the sender in E.164 phone number format.
This variable is essential for our case because we will need to keep track of the users and numbers who are in the directory. As you might have guessed, the message
variable is parsed from the Body
parameter which allows our app to read what the user said and respond appropriately. In this example webhook, the user is asking to check
the roster and status within the directory.
Lastly, since we have to keep track of our colleagues, represented as their phone number, as well as their statuses, a Python dictionary will do the work for us.
This data structure allows us to have one unique key, representing the person’s phone number. Each key will have it’s own status that can be updated. It is also a returnable object that conveniently lists out all the keys (students) and their values (statuses).
Reply to a message
Next, we will be discussing the respond()
function that is called inside of the else
statement. This function is called throughout the project to confirm with the user that we received their text message.
The webhook allows us to issue a response to the student, the one who sent the message, by providing a TwiML payload in response to the webhook. TwiML is short for Twilio Markup Language, an XML-based syntax that the webhook can use to tell Twilio how to handle the message.
The Twilio Helper Library for Python allows us to generate TwiML responses using classes and objects. Let’s check out how we can write our respond()
function:
Add the new import line to the top of the accountability.py file and the new respond()
function above or below the webhook.
If you are curious to see what TwiML looks like, start a Python shell and enter the following code to generate an example response:
Set up testing environment
Awesome job writing your first webhook!
Now it’s time to test it out and make sure it’s running properly by sending and receiving a few text messages. Add a .flaskenv
file (make sure you have the leading dot) to your project with the following lines:
These incredibly helpful lines will save you time when it comes to testing and debugging your project.
FLASK_APP
tells the Flask framework where our application is locatedFLASK_ENV
configures Flask to run in debug mode
These lines are convenient because every time you save the source file, the server will reload and reflect the changes. Neat huh?
So, we’ll move forward by starting our Flask application with the following command:
The screenshot above displays what your console will look like after running the command flask run
. The service is running privately on your computer’s port 5000
and will wait for incoming connections. You will also notice that debugging mode is active, and that my flask server restarted to reflect my changes.
While flask is running in one terminal window, open up a second tab or terminal window. Start ngrok with the following command:
Great, you have now enabled your Flask service publicly over the Internet!
Ngrok is a great tool because it allows you to create a temporary public domain that redirects HTTP requests to our local port 5000
.
Note that if you are unable to install ngrok system-wide, try to locate the executable ngrok file in order to call it in your terminal using its full path.
Your ngrok terminal will now look like the picture above. As you can see, there are URLs in the “Forwarding” section. These are public URLs that ngrok uses to redirect requests into our flask server.
Set up a webhook with Twilio
Copy the URL starting with https://
and return to the Twilio Console, where we tell Twilio to send incoming message notifications to this URL.
In the Twilio Console, click on the (...) on the left sidebar to scroll down and find Phone Numbers. Click on the active phone number that you want to use for this project and scroll down to “Messaging”.
Paste the URL copied from the ngrok session into the “A MESSAGE COMES IN” field and append /webhook
, since that is our endpoint. Here is my example for reference:
The URL from ngrok is “https://ad7e4814affe.ngrok.io/webhook”
Before you click on the “Save” button, make sure that the request method is set to HTTP POST
.
Time to test things out! Grab your SMS-enabled phone and send a text message to your active Twilio number.
Welp, guess that means we need to build out the directory now. At least we know the text messages are working!
Build your Work Accountability Group Organizing app
We’ve made it this far and we have seen how to receive messages from our Twilio number and respond to them. However, we need to spend time creating and personalizing our directory system.
Add yourself to the directory
To add yourself to the directory, we need to write some conditions in our webhook and reply with an appropriate message. If you’re already registered, the program should welcome you back.
Here’s the code that accomplishes that for you, along with an example of what your texts should look like at this point:
Now you can text your Twilio number with the message “hello” to register yourself.
You can add these lines of code below the other code you have inside your webhook already.
Set up and change the student status
As a developer, it is more efficient to create functions when you know you’ll use them in multiple places.
We can create a set_status
function to avoid writing the same lines of code multiple times. Instead, you can simply call a function passing in a status
and the student
variable:
For my statuses, I decided to use a numbering system to make it easier for the users to interact with the directory. I also implemented a condition to ensure that I exist in the directory before changing the status. If I’m in the directory, the program checks my message
and proceeds to change my status.
Here are some example options included within the webhook’s if
statements:
You can insert these if
statements under the if message == 'check':
line. Repeat the process of writing if
statements, status codes, and messages until you are satisfied with your system.
Keep each other accountable
So far, one way to check if your colleagues are being productive is to text check
to the Twilio number. However, it’s not healthy to work all day without breaks. In fact, it’s essential to take your mind off work for a while, even if it’s only for 10 minutes.
We’re going to use a new function called ‘render_template()’ which I’ll explain further in the next section. For now, add this to the top of your accountability.py file with the other packages you imported.
Earlier, we set up a .env file so that we can authenticate against Twilio’s services. This allows us to access the Twilio CLI’s built in functions to retrieve our history of recipient_messages
.
In the code I’m about to show you, I created a new array named recipient_studied_list
to put the data of the user and their timestamp into string format so that it’s easier to read. Notice that I also changed my timezone to PST by adding timedelta(hours = -7)
to all the timestamps, which you can adjust for yourself as well.
As you can see, I created a route for the flask
app to make an HTTP GET
request where users in the directory can go to our unique ngrok
URL with the appended parameter /studycheck
appended at the end. For example, my link would be “https://ad7e4814affe.ngrok.io/studycheck”. You can share this URL amongst the people in your directory so they can all check on one another and view the history of what time people studied throughout the day.
In the next section, we’ll design a simple HTML page that can display the information clearly.
Style a simple HTML page
Now, I’ll show you some code to return HTML from Flask to display the history of status updates in a web browser.
In your accountability
directory, create a folder named templates
. Inside of that folder, create a file named index.html
and copy this code inside.
Your Flask app can now use the render_template
function that we imported earlier to display the index.html
page and pass in any variables you want! Whoever has the URL can access this simple page on their web browser to view the history of responses.
Here’s a screenshot of the web browser view:
On the flip side, you can copy the code but alter it to check if someone is taking too many breaks. By having information from both those who studied and those who took a break, you and your colleagues can check just how often people report themselves to take a break.
If you see an odd trend for someone, maybe you can reach out to them and see if they need someone to talk to!
(Optional) Message restrictions
An optional addition to your code is to handle the scenario where one of your friends accidentally sends an incorrect message that doesn’t do anything. To lead them on the correct path, it might be helpful to create a help_text()
function that returns some text explaining how to use the system.
Here’s an example of what a help message could look like:
Run the Work Accountability Program
It’s time to wrap things up and make sure your program is working the way you want it to. If you want an example, view my code on GitHub.
Make sure you have one tab running flask
and one tab running ngrok
. If you closed it for any reason, start it again now with the following commands in their respective tabs.
And in the second tab:
Furthermore, make sure that your SMS endpoint is configured with the forwarding URL reported by ngrok. Each time you restart ngrok, the URL changes, so you will have to replace the URL in your Twilio Active Phone Numbers console. Remember to add the /webhook
at the end of the ngrok forward URL.
It’s time to form your accountability directory with colleagues who want to help each other stay productive and get that bread! Be sure to tell your friends your Twilio Number so that they can text in, register themselves in the database, and update their status!
Conclusion: Building a Work Accountability app
You must be working productively if you made it this far, and now it’s time to help each other stay healthy while working! This simple SMS tutorial shows you how to create a database of students, coworkers, or colleagues who can update their statuses simultaneously throughout the day with the help of Python and Flask.
If people are using their phones to distract themselves, then this app is a great way to help people use their phones to be productive!
What’s next for Work Accountability apps?
Looking for ideas on how to expand? Try these:
- Add Twilio’s Programmable Video to keep each other company while working from home
- Implement a notification system to ping users every hour and make sure they take a break
- Styling Flask to render the list results of people studying to look more appealing
Let me know if this app makes your productive work days more fun and healthy!
Diane Phan is a Developer Network Intern on the Developer Voices team. She loves to help beginner programmers get started on creative projects that involve fun pop culture references. She can be reached at dphan [at] twilio.com.
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.