Preview Spotify Songs With A Phone Call Using Elixir, Phoenix, Twilio, and the Spotify API

July 01, 2016
Written by

TwilioandSpotify

In a few email exchanges with Nathan Leinz, one thing became clear. We, the royal we, have no excuse not to complete that side project.

When Nathan isn’t busy defusing and disposing of bombs on the Army’s Explosive Ordnance Disposal, he’s working on hacks with a firm sense of purpose. “I’m a firm believer that we should accept where we are, strive to do better, and not have any regrets,” says Nathan.

Nathan taught himself to code while deployed in Iraq, serving in the Army. He quickly progressed from building a Java-based Ant Colony Optimization algorithm, to an iOS Sudoku solving app, to building out the challenge delivery system and progress tracker for FreeCodeCamp — which he was enrolled in at the time.

His latest work is a Twilio and Spotify integration that lets you send previews of songs via phone call. Nathan wanted to hack more using Node.js and Express.js, and thus his “happy little project” was born. You can read his post, originally published on Medium, with a ton of excellent GIFs and a solid Bob Ross reference, right here.

Happy Little Projects: Elixir, Phoenix, Twilio, and the Spotify API

I recently discovered a project idea with a nice pacing to it: a basic Node.js and Express.js application using Spotify’s API and Twilio.

If you’d like to follow along with the JavaScript version, check out this video. If you want to build it in Gradle and Spark, here’s Twilio’s original post.

For this article, we’ll build this app using Elixir and Phoenix. Let’s get started.

Here’s the general flow of the app:

  • You text the title of a song to a Twilio number
  • Twilio makes an HTTP POST to a preconfigured url with some infomation including the song title and information about the requester
  • The application searches the Spotify API for the song, and parses out a preview url
  • The application dispatches a message to the Twilio API. This includes the number to call and a url to fetch some TwiML(Twilio Markup Language)
  • Twilio fetches the TwiML from our application, calls the recipient, and plays them the song preview.

I’ve been through a majority of the curriculum at Free Code Camp. I helped design and build a large part of the core systems behind Free Code Camp, so I’m very comfortable with JavaScript. Following along with the presentation was easy, and I was quick to recreate it. The questions was, could I do it with a language and framework I didn’t have solid experience with?

If you’d like to know what the finished product looks like, text the title of a song to +1 (334) 721–2652. Don’t worry, we won’t save your phone number or song. Request all the ABBA you want!

NOTE:  I’m hosting it on Heroku so it may take a moment to wake up and respond.

Using Elixr

I wanted to challenged myself and play with a language that I’ve been smitten with since hearing about it. Elixir is a gorgeous language with Ruby inspired syntax. Elixir runs on the BEAM (Erlang VM), and is interoperable with Erlang. Yes, Erlang of WhatsApp fame. I love the idea of being able to tap into that kind of power and reliability. I also love functional programming.

On top of Elixir, I’m also a fan of the Phoenix web framework. It’s easy to get started with, and easy to get things done in. The error messages are excellent and tend to tell you exactly how to fix them. Trust me on this, I’ve seen enough of them.

The first task is is to generate a new Phoenix application. I called mine Philter, so I typed:

mix phoenix.new philter --no-ecto --no-brunch

With this, we’re creating a new phoenix application called Philter, with no database layer and no JavaScript build system. We won’t be using any JavaScript in this project!

Follow the on-screen instructions to finish setting up the application. We’re now ready to work through our list of tasks.

Using Twilio

Twilio makes it pretty easy to setup an account. As an aside, their documentation and console are top notch. It’s one of my favorite web services to use.

Sign up for Twilio here. If you want to follow along with this tutorial, you’ll have to add some funds. $5 would be more than enough to give you days of playing around. If you decide to follow along, buy a phone number and keep your browser tab open.

Ngrok

The next service you’ll want to use is ngrok. This handy little service tunnels into a specified port on your computer and gives you a public url to use. The service is completely free, but I signed up for the $5/mo plan so I could have a reserved subdomain. It’s the little things, I tell ya.

Open a new terminal tab and install ngrok via npm. Then use ngrok to specify that you’d like to create an http tunnel to port 4000 on your computer. Check out the documentation here.

~ iex -S mix phoenix.server
      # 
~ mix phoenix.server

The first option starts the server in an interactive shell that will let you interact with it. Regardless of your method of starting it, you’ll see it log out that it’s listening on your local machine on port 4000.

Now open a new browser tab and visit localhost:4000 to confirm it’s working. Then, paste in the url from the Forwarding http line in the ngrok terminal.

Go back to the tab you have your Twilio console open in, and find your phone number. Click on it, and you should see some configuration information. Under the messaging section, “When a message comes in”, enter the url from ngrok followed by “api/sms”. Ensure the HTTP method is set to POST. For reference, while building this application mine was set to http://tkb.ngrok.com/api/sms

tkbtwilio

While we have the Twilio console open, get your ACCOUNT SID and AUTH TOKEN credentials. You can find them by clicking on your account name in the top right hand corner of the window and looking at the “API Credentials” section. Create two environmental variables, TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN. I use an extension of the preferences panel on my Mac called EnvPane. You can also search google and get a ton of results if you need help setting yours.

With all that information at hand, we’re nearly ready to tie it all together. We have one last thing to configure. We’re going to use ExTwilio, a library to help our phoenix application talk to Twilio.

Open config/config.exs and add the following above the final import statement:

config :ex_twilio,
  account_sid: System.get_env(“TWILIO_ACCOUNT_SID”),
  auth_token: System.get_env(“TWILIO_AUTH_TOKEN”)

Here’s where we’re telling our application to read in these two environmental variables so we can send messages and make phone calls through Twilio’s API.

In your favorite editor of choice (mine is Spacemacs), open your Phoenix application directory. Let’s get down to business.

Open web/router.ex and get rid of any scope stuff you see. Replace it with:

scope “/”, Philter do
  pipe_through :browser

  post “/twiml”, TwimlController, :index
end

scope “/api”, Philter do
  pipe_through :api

  post “/sms”, SmsController, :index
end

 

Replace any mention of Philter with whatever name you gave your application.

The above code did a few things. We have a created a route that will match POSTs to http://yourngrokurl/twiml and route to TwimlController’s index function. We also did the same for the http://yourngrokurl/api/sms route, passing off to SmsController’s index function. Learn more about routing in Phoenix by checking out the excellent documentation.

Now create two files in the web/controllers/ directory, sms_controller.ex and twiml_controller.ex. Make your s ms_controller.ex look like:

defmodule Philter.SmsController do
  use Philter.Web, :controller

  alias Philter.Sms

  def index(conn, %{"Body" => song, "From" => from, "To" => to}) do

    Task.start_link(fn -> search_spotify(song, %{from: from, to:     to}) end)
    send_resp(conn, 200, “”)
   end

  defp search_spotify(song, twilio_data) do
    Philter.Spotify.search(song, twilio_data)
  end
end

To those Elixirists reading this, please keep in mind I’m still very much learning. With that disclaimer out of the way, on to a brief explanation.

Twilio will post the phone number of the requester in a From field, our Twilio number in the To field, and the body of their text in the Body field. We’re fishing those out, then spawning a task to search the Spotify API.

Spawning a task executes some long running function in a super lightweight BEAM process. If something happens to the process, like it crashes or catches on fire or is stricken by cosmic rays, our application will happily continue accepting connections and prevent moments of developer panic.

A full discussion of Tasks and OTP in general is far beyond the scope of this article. Please refer to the Elixir links in this post if you’d like to learn more about this amazing beast.

Now refer to the GitHub repository for this project. The files you’ll want to copy are lib/philter/spotify.ex and the entire lib/philter/spotify/ directory. Ensure you go through the files, changing any mention of Philter to your own application name. In spotify.ex, on line 55, replace “tkb” in the url to whatever your ngrok url is.

Now make your twiml_controller.ex look like the following:

defmodule Philter.TwimlController do
  use Philter.Web, :controller

  alias Philter.Twiml

  def index(conn, %{"song" => song) do
    render(conn, “index.html”, song: song)
  end
end

All we’re doing here is fishing the song out and and then passing it along as a variable to our template.

Open the app.html.eex in the web/templates/ directory and delete everything except for:

<%= render @view_module, @view_template, assigns %>

We don’t need any of that other markup!

Next, create a file under the web/views/ directory called twiml_view.ex. We could put helper functions in here, but we don’t need any so it’s just going to live as a shell file. The contents should be:
defmodule Philter.TwimlView do  use Philter.Web, :viewend

Now create a new directory under web/templates/ called twiml/ and inside of it create a file called index.html.eex. The contents are straightforward:

<?xml version=”1.0" encoding=”UTF-8" ?>
 <Response>
   <Say>Please enjoy the clip!</Say>
   <Play><%= @song %></Play>
   <Say>I hope you enjoyed your song clip</Say>
 </Response>

This is the response we’ll send to Twilio when they ask us for TwiML in response to our API interaction within the task I barely touched on. Feel free to play around, and reference the great TwiML documentation.

With a restart of Phoenix, you should be able to text your Twilio phone number and get a phone call with the song preview!