Day 19 of the Anvil Advent Calendar

Build a web app every day until Christmas, with nothing but Python!

Christmas SMS countdown

We’re already watching the calendar, thanks to advent day 3, and yesterday’s app. But, what if we could get a text message every day to let us know how close we are to Christmas? Wouldn’t that be lovely? No? Well, I’ve done it anyway.

Read on to learn how, or you can open the source code for yourself:

Request data from the API

We already created an API endpoint for the days to Christmas on day 8:

https://christmas-days.anvil.app/_/api/get_days

I’ll use this API to get the days to Christmas.

Create a new Anvil app and add a Server Module. Add a get_days function to your Server Module:

import anvil.http

def get_days():
  # Get data from the API
  response = anvil.http.request("https://christmas-days.anvil.app/_/api/get_days",json=True)
  days_until_christmas = response['Days to Christmas']
  return days_until_christmas

Create the UI

We want our users to be able to sign up to receive their Christmas countdown by SMS.

We’ll create a simple UI using a TextBox and a Button to capture and Submit user inputs.

Our basic UI looks like this:

Note: This guide includes screenshots of the Classic Editor. Since we created this guide, we've released the new Anvil Editor, which is more powerful and easier to use.

All the code in this guide will work, but the Anvil Editor will look a little different to the screenshots you see here!


Store user phone numbers

We want to store our registered users’ numbers in a database so we can send them an SMS every day. We’ll use Anvil’s Data Tables to do this, and the setup looks like this:

Let’s add a server function to store numbers in this table:

@anvil.server.callable
def store_number(number):
  app_tables.numbers.add_row(phone_no=number)

Go back to your UI and double click on the Button. Modify your button_1_click() method to look like this:

  def button_1_click(self, **event_args):
    # Get the phone number from the TextBox
    number = self.number_box.text
    # Call the `store_number` server function
    anvil.server.call('store_number', number)

We’ll call this function from the client when the ‘Register’ button is clicked.

Send a text message

We’ll use the Vonage API to send our text messages. You’ll need to create a Vonage account to get your api_key and api_secret. Once you have these, use Anvil’s App Secrets to store these, encrypted, in your app:

Next, create a server function called send_text() which will send our texts. We’ll decorate it as @anvil.server.background_task:

@anvil.server.background_task
def send_text():
  api_key = anvil.secrets.get_secret('api_key')
  api_secret = anvil.secrets.get_secret('api_secret')
  # Call our `get_days()` server function to get days from the api
  days_to_christmas = get_days()
  # Get our phone numbers from the Data Table
  numbers = app_tables.numbers.search()
  for n in numbers:
    response = anvil.http.request("https://rest.nexmo.com/sms/json", method="POST", json=True,
                     data={
                       'api_key':api_key, 
                       'api_secret':api_secret, 
                       'to':n['phone_no'], 
                       'from':'Anvil',
                       'text':f"There are {days_to_christmas} days until Christmas! \U0001F31F \ud83c\udf84 \ud83c\udf85",
                       'type':'unicode'
                       }
                     )

Create a countdown

We want to send a Christmas SMS once a day to everyone who’s registered for our countdown. We’ll use Scheduled Tasks to do this.

Select Scheduled Tasks from the Gear Menu, and set the send_text() function to run once a day:

Click the green tick to save your task.

Let the countdown commence!

That’s all there is to it. Anyone who registers will now get a Christmassy countdown every day!

View the source code:


Give the Gift of Python

Share this post: