ecently, my friends Chloe, Bianca and I were invited to NASA to take part in a behind-the-scenes tour and briefing on five new research campaigns that will take to the field in 2020 to explore questions critical to understanding our home planet! With so much to look forward to, I decided to create a countdown for the days leading up to our road trip! Rather than execute the group chat countdown manually, I decided to get a little help from my friends at Twilio, Azure Functions and use the NASA's astronomy picture of the day API. My goal was to accomplish the following:
- Countdown the number of days remaining until the trip to NASA
- Include NASA's astronomy picture of the day
- Schedule a message to be sent every morning at 9AM
Here's an example of a message:
Sign Up for Twilio and Get a Phone Number
In order to work with Twilio’s products, you’ll need to sign up and purchase a voice enabled phone number. If you’re new to Twilio, you can start with a free trial. For further assistance on signing up and purchasing a phone number, visit Twilio.
Generate a NASA API Key
You'll need an API Key to use the NASA Astronomy Picture of the Day API. It's FREE and includes 1000 requests per minute.
Sign Up for an Azure Subscription
You can create a FREE Azure Subscription to setup your Azure Function. The free trial will provide you with 12 months of free services.
Visit my GitHub repository to access the code that will be used throughout the tutorial.
UPDATE: I published a new version of this tutorial over on the Twilio Blog. Please refer to that tutorial!
Since we'll be creating an Azure Function later using the Azure Functions Extension in Visual Studio Code, I'd suggest creating a folder now for the entire project. Azure will create some files that are necessary to get the function to work so it's better to get things organized now rather than have to move files around later.
Create and save a new Python file in Visual Studio Code. There are a few modules which need to be imported so that we can create the logic within the goals of this project:
Since we're working with GET requests, you'll need to import the requests module so that we can get data from the NASA API.
You can install the module using pip install requests.
The Twilio Python Helper Library makes it easy to interact with the Twilio API from the Python app.
You can install the Twilio Python Helper Library using pip install twilio.
I'm a huge emoji lover and want to ensure that I can include emojis in the text message. Fortunately, the emoji module will enable you to use emojis in your strings! I'll cover this later in the tutorial, however, this Emoji Cheat Sheet is really helpful for figuring out the emoji code for whatever emojis you want to include in the text message.
You can install the module using pip install emoji.
Since the text message countdowns the number of days until we head to NASA, there needs to be logic that takes the current date and subtracts the number of days until some targeted date. The datetime module not only gives you the current date but also includes a timedelta object that can be used to determine the difference between two dates!
This module comes with Python so there's nothing to install for use.
After you install the modules, you can import them into the code using import. For the Twilio Python Helper Library, import Client. For datetime, just import date.
Setup Date Countdown Variables
There's a few variables that need to be created so that you can get the difference between two dates. These variables will also come in handy later when you create the text message. First, create a variable which represents today's date using the date object and the .today() method.
Next, to subtract the two dates, you'll need to get the dates in the proper format. The format is: Year, Month, Day (ex: 2020, 1, 6 is January 6, 2020). First, create a variable which converts today's date to the proper format followed by a variable for the target date (i.e. the date we go to NASA).
Finally, create a variable which stores the difference between the two dates. You can use regular arithmetic to get the difference.
Setup NASA API Get Request
Let's get some data from NASA! The NASA Astronomy Picture of the Day API returns quite a bit of information alongside the actual photo. We'll just need the title and the photo for the text message that'll be generated daily. Create a response variable that stores the get request for the API. Be sure to get the json response as well! You can store that in it's own variable as well.
The json outputs the photo as a URL. Store this in it's own variable. And finally, create a variable for the title of the photo.
Oh, before I forget, create a variable for the rocket emoji! Who doesn't think of rockets when they hear the name NASA? The emoji module will be helpful here. You can use the .emojize() method with emoji and insert the emoji code inside the method.
Create Twilio Message
Now it's time for some Twilio fun! Twilio provides a template that you can use - which is a huge time saver. Let's walk through the template.
There's a few variables that are created so that you can use your Twilio account credentials. Replace the placeholders in the account_sid and auth_token variables with your own values. The client variable uses both variables as parameters.
Next, the message is created. The body contains the text that will be sent to the receiver's phone. You can craft the message however you'd like, however, I suggest using string formatting with f syntax to include the variables we created from the NASA GET request.
Replace the from variable's placeholder with your Twilio number. Be sure to start the number with the country code! The same rules apply for the to variable's placeholder - however, insert the receiver's phone number.
Circling back to the media_url variable, you can replace the placeholder with the photo variable from the NASA GET request. Be sure to use string formatting with f-syntax so that the URL can be passed into the brackets.
You can test everything by running the code. Make sure to have the receiving phone nearby so that you can check whether the text message comes through. Feel free to change the message body until the text looks exactly the way you'd like.
Sign in to Azure in VS Code
Now that we have the Twilio SMS logic squared away, we need to create an Azure Functions Timer Trigger that will send the text message daily at 9AM. We'll create the trigger to initially run for every minute just to ensure that all is working properly. However, we'll modify the trigger to daily at 9am after we confirm that the function is working.
Rather than reiterate everything that's been documented by Microsoft, follow the steps outlined in the Introduction and Prerequisities to get setup with Azure and login to Azure in Visual Studio Code.
Create a New Project
After verifying that you're signed in to Azure, click Create New Project (this will be in the top menu for the Azure menu in VS Code) and select the folder that you created earlier at the start of this tutorial. This folder is where the Azure Function files will be created. Visual Studio Code will guide you through the instructions for creating a new function, however, I'll walk you through the steps as well!
Select Python as the language TimerTrigger as the template. Keep the Cron expression as-is - we'll update that later! Name the function something to the effect of TextTimer and set the Authorization Level as Anonymous. You can choose to open your project in the current window.
Azure will begin to work it's magic to create the function - you can check the progress in the status bar at the bottom of Visual Studio Code. Once Azure is done, the __init__.py file will open.
Azure creates a virtual environment for the function. To use the modules that we imported earlier in our code, you'll need to install the modules once more.
- pip install azure-functions
- pip install requests
- pip install twilio
- pip install emoji
Add Twilio Logic to the __init__.py File
The __init__.py file contains a template for a TimerTrigger. We'll be adding the Twilio logic from earlier to this file within the main function. Using the code in the file where you wrote your Twilio logic, copy and paste the import modules into the __init__.py file. I would suggest placing the modules at the top of the file to keep all your imports together.
Paste your Twilio credentials and the client variable below the imports. You can create environment variables later, however, we need to test everything before deploying to Azure so for now, they'll be hardcoded in the __init__.py file.
Now comes the fun - we'll add onto the main function in the template. Make sure to maintain your indents - otherwise the main function will get wonky. Paste the remainder of the Twilio logic below the logging.info line. Again - maintain your indents! Once you're done modifying the __init__.py file, save the file.
Add Requirements to requirements.txt
Open the requirements.txt file. We'll need to add the modules that we imported into the code. Add the modules and save the file.
Before you deploy the function to Azure, test everything by running the debugger. Right now, the code defaults to generating a text every 5 minutes. However, if that's too long of a wait, you can adjust the CRON expression in the functions.json file. I would suggest changing the 5 to a 1 if you want the trigger to send the text every minute. If you choose to update the CRON expression, be sure to save the file and return to __init__.py.
From the __init__.py file, start debugging from the Debug tab. Visual Studio Code will prompt you to select a Resource Group. If you already have one, then feel free to select from the options available. Otherwise, create a new Resource Group. After the Resource Group has been created, you're ready to test the function. Start the debugger if it doesn't start after selecting/creating the Resource Group.
Depending on the CRON expression you chose, the text will send after the first event triggers.
If your phone receives the text message, then great! If not, check out the error messages. I would suggest revisiting the steps above to ensure that you followed everything in the prior steps correctly.
Update CRON Expression
Before you deploy to Azure, adjust the CRON expression in the function.json. By default, the Azure function uses the UTC time zone. Therefore, you need to set a time in that time zone that equates to 9AM in your specific time zone. Since I'm in California, I follow Pacific Standard Time. Therefore, my CRON expression for everyday at 9AM would be: 0 * 17 * * *. For those of you on the east coast, the CRON expression would be: 0 * 14 ***.
If you fall outside either of those timezones, you can use this converter to figure out the equivalent to 9AM for UTC in your time zone.
Update the CRON expression and save the function.json file.
Deploy to Azure
Make sure that all files are good before beginning deployment. You will not be able to edit the files in the Azure Portal. Once you've saved everything, click on the Azure tab in Visual Studio Code and select the project. Next, click the deploy icon (it's an arrow pointing up). You will be prompted to provide a unique name for the app. Feel free to use an existing resource group, however, you could also create a new one. Complete the remaining prompts to begin the deployment.
You can check the status of the deployment in the Output window. It takes a few minutes for your first deployment to complete, however, if you ever need to do another deployment for the function, it'll happen faster.
After the deployment is complete, the function can be viewed in the Azure portal. If you ever need to make adjustments to the files, you can do so locally in Visual Studio Code and deploy the app again. When prompted, overwrite the previous deployment.
You can also set environment variables for your API keys in the application settings for the function. Just be sure to replace the values with the environment variable in the __init__.py file.
Once you're done with everything, you can type deactivate in the terminal to quit the virtual environment for the project. If you're not going to continue to use the function, clean up the resources by right-clicking the Function App in the Azure: Functions explorer and select Delete Function App. Otherwise, the app will continue to run and you'll incur a minimal cost.
You can also visit the Azure portal, select Resource groups from the left-side navigation pane, select the resource group that was created in the process of this tutorial, and then use the Delete resource group command.