Create Secret Santa Matches Using Python Flask and Twilio SMS

December 24, 2021
Written by

Create Secret Santa matches using Python Flask and Twilio SMS

For the second year in a row, my family decided to embrace the “secret santa” method of giving gifts at Christmas. Rather than everyone getting a gift for everyone else, which can be expensive and time consuming, each person’s name is put in a box and we each draw one name from the box. The name we draw is the person we give a gift to, up to a certain dollar amount that we’ve all agreed on in advance.

This year, my family is spread all over the United States so it wasn’t possible to draw names from a box. Instead, I thought it would be fun to create my own Flask application that would match people up and notify each person of their gift recipient using Twilio SMS.

Follow along with the tutorial below, or clone the GitHub repository if you’re in a rush!

Prerequisites

A screenshot of the Twilio Console showing where to locate the Account SID and Auth token

Create the Python virtual environment

Create a new directory for this project in your command prompt called flask-secret-santa-sms/, then navigate to this new directory:

$ mkdir flask-secret-santa-sms
$ cd flask-secret-santa-sms

We will create a new virtual environment for this project so that the dependencies we need to install don’t interfere with the global setup on your computer. To create a new environment called “env”, run the following commands once you’ve navigated to the flask-secret-santa-sms/ directory:

$ python3 -m venv env 
$ source env/bin/activate

After you source the virtual environment, you'll see that your command prompt's input line begins with the name of the environment ("env"). Python has created a new folder called env/ in the flask-secret-santa-sms/ directory, which you can see by running the `ls` command in your command prompt.

Create a file called .gitignore in the flask-secret-santa-sms/ directory as well.

(env) $ touch .gitignore

Open the .gitignore file in the text editor of your choice, then add the env/ folder to the contents of the .gitignore file:

env/

Note that the env/ folder created by Python for the virtual environment is not the same thing as the .env file that’s created to store secrets like API keys and environment variables.

Store environment variables securely

You’ll need to use the Account SID and Auth Token you located at the beginning of this tutorial in order to interact with the Twilio API. These two environment variables should be kept private, which means we should not put their values in the code. Instead, we can store them in a .env file and list the .env file in our .gitignore file so git doesn’t track it. A .env file is used whenever there are environment variables you need to make available to your operating system.

> Note that the env/ folder created by Python for the virtual environment is not the same thing as a .env file created to store secrets.

First, create the .env file:

(env) $ touch .env

Then, add the .env file as a line item in the .gitignore file:

env/
.env  # Add this

Next, open the .env file in your favorite text editor and add the following lines, replacing the random string placeholder values with your own values:

export TWILIO_ACCOUNT_SID=AzLdMHvYEn0iKSJz
export TWILIO_AUTH_TOKEN=thFGzjqudVwDJDga

Source the .env file so it becomes available to your operating system, then print the environment variable values to your console to confirm they were sourced successfully:

(env) $ source .env
(env) $ echo $TWILIO_ACCOUNT_SID
(env) $ echo $TWILIO_AUTH_TOKEN

Install the Python dependencies

The Python packages required for the project are:

  • twilio - provides access to the What’sApp API
  • flask - provides the web server for our project

Dependencies needed for Python projects are typically listed in a file called requirements.txt. Create a requirements.txt file in the flask-secret-santa-sms/ directory:

(env) $ touch requirements.txt

Copy and paste this list of Python packages into your requirements.txt file using your preferred text editor:

twilio
flask

Install all of the dependencies with the command given below, making sure you still have your virtual environment (“env”) sourced.

(env) $ pip install -r requirements.txt

Create the Flask server

It’s time to write some code! In the flask-secret-santa-sms/ project directory, create a new file called app.py:

(env) $ touch app.py

Open the app.py file in your preferred text editor and add the following code, which imports the dependencies, pulls in our environment variables, and creates a simple Flask server:

import os
from random import shuffle

from flask import Flask, render_template, request, url_for
from twilio.rest import Client


# Setup Twilio credentials and REST API client
TWILIO_ACCOUNT_SID = os.environ.get('TWILIO_ACCOUNT_SID')
TWILIO_AUTH_TOKEN = os.environ.get('TWILIO_AUTH_TOKEN')
client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)

# Setup Flask app
DEBUG = False
app = Flask(__name__)

Create an HTML form that accepts participants’ phone numbers

On the homepage of our Secret Santa app, we’ll show a simple HTML form where you can enter the phone numbers of your group’s participants. For this tutorial, we’ll include text fields for 4 participants.

You can change the number of text fields to match the number of people in your group by deleting any extra text fields shown in the HTML code below, or by adding new text fields. If you’re adding new text fields, make sure each text field has its own unique id and name. The code we’re going to write will dynamically determine how many text fields there are, so you won’t need to change anything in the code if you want to change the number of people in the Secret Santa group.

In the flask-secret-santa-sms/ directory, create a templates/ directory to store our HTML file. Then, create an index.html file inside of the new templates/ directory.

(env) $ mkdir templates
(env) $ touch templates/index.html

Copy and paste this code into your index.html file. It's a simple HTML form that includes text fields for each participant's name and phone number.

Display the HTML form on the home page

Now that we have the HTML form to collect all the phone numbers, we need to create a Flask route to serve the form. For simplicity, we’ll show this form on the home page of our application. Add this new route to the bottom of the app.py file, which simply renders the HTML form on the home page:

@app.route('/')
def index():
    return render_template('index.html')

Create a Flask route to handle the HTML form data

Now that we have an HTML form, it’s time to write a function that will process the data that comes through in the form.

Copy the create_assignments() function found on lines 21 - 61 of the app.py file in the GitHub repo and paste it at the bottom of your own app.py file. The function does the following:

  1. Intakes the form data
  2. Separates the name and phone number information into separate lists
  3. Sorts each list so that each participant’s name and phone number appear at the same index of each list
  4. Creates the Secret Santa matches
  5. Calls a helper function that sends the SMS notifications

Create a helper function to send the SMS notifications

The last thing we need to do is write a function that handles sending the SMS notifications. Copy and paste this function into the bottom of your app.py file, underneath the create_assignments() function you added in the previous step.

Remember to change the placeholder from_ number in the example code below to your own Twilio phone number, making sure to maintain the E.164 format.


def send_assignments(assignments):

    successful_notification_counter = 0
    for gift_sender, gift_recipient in assignments.items():
        body = "{}, you are {}'s Secret Santa this year. Remember to get them a gift!".format(
            mapped_user_info[gift_sender],
            mapped_user_info[gift_recipient]
        )

        try:
            message = client.messages.create(
                 body=body,
                 from_=+12345678901,  # CHANGE THIS to your own Twilio number
                 to=gift_sender
             )
            print("Secret Santa assignment sent to {} via SMS".format(mapped_user_info[gift_sender]))
            successful_notification_counter += 1

        except Exception as e:
            print(e)
            print("There may have been a problem sending the notification to {}".format(mapped_user_info[gift_sender]))
            continue

    print("Notifications sent to {} people".format(successful_notification_counter))
    return

Remember, this function is called within the create_assigments() function. It sends an SMS message to each participant to notify them of who they should give a gift to.

Start the server

It’s time to start the server and try this out! While you’re in the flask-secret-santa-sms/ directory, run this command to start the Flask server:

(env) $ flask run

Navigate to localhost:5000 in your web browser. Enter the names and phone numbers for each of the 4 participants, then click the button at the bottom of the form to continue. Behind the scenes, our create_assignments() function will create the Secret Santa pairs, then call the send_assignments() helper function to send the SMS messages. Check your phone to see if the SMS message came through, and also check your CLI output for more details that were printed from the Python script.

Note: Because of how the matching logic works, you cannot enter a phone number more than once. Thus, if you want to test this out before running it on a real group, you’ll need a few people to agree to be part of your test.

Congratulations!

You now have a working application to assign Secret Santa pairs for your family or group! You just learned how to:

  • Create a web server using Flask
  • Receive and manipulate data from an HTML form
  • Send SMS messages using Twilio’s API

Next steps

If SMS isn’t the right mode of communication for the people in your Secret Santa group, you could modify this tutorial to use one of these instead:

Or, check out the Build A Secret Santa Bot for WhatsApp Using Python and Twilio tutorial on the Twilio blog.

I can’t wait to see what you build!

Author bio

August is a Pythonista on Twilio's Developer Voices team. She loves Raspberry Pi, real pie, and walks in the woods.