Building Python web apps with Flask

March 24, 2017
Written by
Sam Agnew
Twilion

flask-oauth

DISCLAIMER: In the time since this post was published, the Spotify API changed to no longer allow unauthorized requests. Some of the code involving use of the Spotify API will not work as-is included in the post.

When getting started with web development in Python, Flask is a great choice due to its lightweight nature. There is already a solid “Hello World” style quickstart in the Flask docs, so let’s walk through building an application with more functionality.

We are going to build a Flask app using the Twilio REST API that will receive SMS messages containing a song title and respond with a phone call playing a clip of that song from Spotify.

Setting up your environment

Before moving on, make sure to have your environment set up. Getting everything working correctly, especially with respect to virtual environments, can be relatively confusing for developers new to Python.

Run through this guide to make sure you’re good to go before moving on.

Installing dependencies

Now that your environment is set up, you’re going to need to install the libraries needed for this app. We’re going to use:

Navigate to the directory where you want this code to live and run the following command in your terminal with your virtual environment activated to install these dependencies:

pip install requests==2.8.1 twilio==6.0.0 flask==0.10.1

 

Requesting data from other APIs

Let’s start by writing a module to interact with the Spotify search API, which is just a URL that returns some JSON.

Create a file called spotify.py and enter the following code:

import requests


def get_track_url(song_title):
    spotify_url = 'https://api.spotify.com/v1/search'
    params = {'q': song_title, 'type': 'track'}

    spotify_response = requests.get(spotify_url, params=params).json()
    track_url = spotify_response['tracks']['items'][0]['preview_url']
    return track_url

What we’re doing here is sending a request using the requests module to the URL corresponding to Spotify’s search API, parsing the JSON response, and grabbing the URL associated with the preview of the first track in our search.

Setting up your Twilio account

Before being able to respond to messages, you’ll need a Twilio phone number. You can buy a phone number here.

Your Flask app will need to be visible from the Internet in order for Twilio to send requests to it. We will use ngrok for this, which you’ll need to install if you don’t have it. In your terminal run the following command:

ngrok http 5000

This provides us with a publicly accessible URL to the Flask app. Configure your phone number as seen in this image:

Screen Shot 2016-07-14 at 10.54.53 AM.png

You are now ready to send a text message to your new Twilio number.

Building the Flask app

Now that you have a Twilio number and are able to grab a preview URL from Spotify, which links to an MP3 of a given song, you want to allow users to text a phone number to provide us with a search query.

Let’s create our Flask app. Open a new file called app.py and add the following code:

import spotify

from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse, Message
from twilio.rest import Client
import urllib

# Account SID and Auth Token from www.twilio.com/console
client = Client('TWILIO_ACCOUNT_SID', 'TWILIO_AUTH_TOKEN')
app = Flask(__name__)


# A route to respond to SMS messages and kick off a phone call.
@app.route('/sms', methods=['POST'])
def inbound_sms():
    response = MessagingResponse()
    response.message('Thanks for texting! Searching for your song now.'
                     'Wait to receive a phone call :)')

    # Grab the song title from the body of the text message.
    song_title = urllib.parse.quote(request.form['Body'])

    # Grab the relevant phone numbers.
    from_number = request.form['From']
    to_number = request.form['To']

    # Create a phone call that uses our other route to play a song from Spotify.
    client.api.account.calls.create(to=from_number, from_=to_number,
                        url='http://sagnew.ngrok.io/call?track={}'
                        .format(song_title))

    return str(response)


# A route to handle the logic for phone calls.
@app.route('/call', methods=['POST'])
def outbound_call():
    song_title = request.args.get('track')
    track_url = spotify.get_track_url(song_title)

    response = MessagingResponse()
    response.play(track_url)
    return str(response)

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

Make sure to replace “YOUR_NGROK_URL” with your actual Ngrok URL in the code for placing the phone call. If you are using Python 2, you also might have trouble with the song_title = urllib.parse.quote(request.form['Body']) line. Replace it with song_title = urllib.quote(request.form['Body']) and things should work better.

We only need two routes on this app: /sms to handle incoming text messages and to place a call using the Twilio REST Client, and /call to handle the logic of that phone call.

Run your code with the following terminal command:

python app.py

Now text your Twilio number and get a phone call with the song of your choice!

What just happened?

With this app running on port 5000, sitting behind our public ngrok URL, Twilio can see your application. Upon receiving a text message:

  1. Twilio will send a POST request to /sms with the number the message came from, the number it was sent to, and the body of the message.
  2. The inbound_sms function will be called.
  3. A request to the Spotify API will be made, receiving a JSON response that then gets parsed to acquire a “preview URL” to an MP3 file.
  4. A call is made with the Twilio Rest Client, with the track title being sent through URL parameters.
  5. Twilio makes another POST request, this time to the /call route to play the song that the user texted.

Feel free to reach out if you have any questions or comments or just want to show off the cool stuff you’ve built.