Twilio is a relatively new cloud-based platform that allows one to
create and scale voice, VoIP and SMS text messaging applications. Here, we'll walk through building an app to allow a caller to check the high and low tide times in Santa Monica for the day of the call. We'll use TwiML, Twilio's XML-like language for issuing HTTP GET and POST requests between your server and theirs.
In order to run your app, you'll need to find a place to host your code. For this example, I'll use a basic
Heroku app. First, we'll build the Heroku app using ruby and
Sinatra, then we'll incorporate the TwiML and the Twilio Sandbox.
If you don't already have a github account and its version control system installed on your local machine, follow
these directions. If you don't already have a Heroku account or aren't setup to push code from your local machine, follow
these instructions. If you have no idea what I'm talking about, perhaps this
panda can set you straight.
Rather than reinvent the wheel, we'll clone an existing
github repository that has a basic skeleton for making one page static sites on Heroku.
# Make yourself a directory for the app
$ mkdir twilio_static
# Pull a clone of the skeleton app
$ git clone git://github.com/dpritchett/wwebsite.git twilio_static/
$ cd twilio_static/
The
./twilio_static/Gemfile looks like this
source 'http://rubygems.org'
gem 'sinatra'
gem 'heroku'
# For Twilio App
gem 'hpricot'
gem 'twilio-ruby'
gem 'builder'
Install the gems...
$ bundle install
Now we need to create a repository on github.
$ git init
$ git add .
$ git commit -m "initial commit"
Go to
github and create new repository on github: https://github.com/<username>
Next, associate the local files with the new repository.
# Got an error because the local name of the remote repository already exists
$ git remote add origin git@github.com:jonesbb/twilio_static.git
fatal: remote origin already exists.
# Found a workaround on Stack Overflow and was able to continue
$ git remote rm origin
$ git remote add origin git@github.com:jonesbb/twilio_static.git
$ git push -u origin master
# now create heroku app
$ heroku create
$ git push heroku master
To get a preview of the basic app, you can run the server locally
$ ruby -rubygems app.rb
Point your browser here to see the app on your local server: http://localhost:4567/
*** You need to restart the app.rb file each time you change it! ***
Get a xml file of
tide data from NOAA and place it in the /public folder of the app. For extra credit you could have the app extract that data directly from the NOAA servers, but that's outside the scope of this demo.
Start a ruby script to parse through the tide data and output the high/low tides for the current day.
Here's what's in the initial version of my
public/twilio_tides.rb
require 'rubygems'
require 'hpricot'
require 'builder'
# Get Today's Date in yyyy/mm/dd format
t=Time.now
cdate = t.strftime("%Y/%m/%d")
# Read in the tides xml file
xml = File.read('public/9410840_2012_tides.xml')
# Initiate the variable, prepending an intro.
@tide_today = ["Today's Tides are as follows:"]
# Find the tide info for today's date
# There's usually more than one hi/lo for a day, so push all into an array
doc = Hpricot::XML(xml)
(doc/:item).each do |dat|
tide_date = (dat/'date').inner_html
tide_time = (dat/'time').inner_html
tide_size = (dat/'predictions_in_ft').inner_html
tide_hilo = (dat/'highlow').inner_html
if tide_date == cdate then
if tide_hilo == "H" then
tide_hilo = "high"
elsif tide_hilo == "L" then
tide_hilo = "low"
end
@tide_today << "#{tide_hilo} tide, #{tide_size}feet at #{tide_time}"
end
end
# Join the array into one string and define instance variable to pass to app.rb
@@tide_today = @tide_today.map! { |p| "#{p}" }.join(", ")
Add to the
app.rb to test out the new
twilio_tides.rb script.
# Setup a test of the tides script
get '/hello' do
puts "Hello, world!"
load 'public/twilio_tides.rb'
puts "Here's tide info: #{@@tide_today}"
end
Run the app locally as discussed above and navigate to:
http://localhost:4567/hello (which initiates the get request to run the code in /hello).
You should see the "Hello World" and "Here's the tide info:..." print with the tide data for today.
Now you're ready for the TwiML creation. The additional code in app.rb below makes use of the TwiML verbs, <Say> and <Gather> to tell the caller what the tides are and then to gather the caller's feedback regarding the option of repeating the info or ending the call.
Here's the final
app.rb file.
require 'sinatra'
require 'builder'
# Define the route for the index.html - static homepage for the app
get '/' do
File.read(File.join('public', 'index.html'))
end
# Setup a test of the tides script
get '/hello' do
puts "Hello, world!"
load 'public/twilio_tides.rb'
puts "Here's tide info: #{@@tide_today}"
end
# Define a method that accepts both post and get requests
# This is useful because of the /loop redirect to /tides
def get_or_post(path, opts={}, &block)
get(path, opts, &block)
post(path, opts, &block)
end
# Create the TwiML response to read out the tide data
get_or_post '/tides' do
load 'public/twilio_tides.rb'
builder do |xml|
xml.instruct!
xml.Response do
xml.Say("Hi #{@@tide_today}")
xml.Gather(:action=>"/loop", :numDigits => 1) do
xml.Say("Press one to repeat or two to end this call.")
end
end
end
end
# Loop the caller's feedback
post '/loop' do
if !params['Digits'] or params['Digits'] != '1'
builder do |xml|
xml.instruct!
xml.Response do
xml.Say("Adios.")
end
end
else
redirect '/tides'
end
end
Now let's push all the code to Heroku so we can access it from Twilio.
$ git add .
$ git commit -m "added TwiML to app"
$ git push
$ git push heroku
Take note of the Heroku
http://sharp-stream-4312.heroku.com
Go to Twilio and create an account (if you haven't got one already). On your account's Dashboard, you'll see the "Sandbox." Put the new Heroku URL, directing to the get_or_post method's /tides, in the Sandbox's Voice URL.
http://sharp-stream-4312.heroku.com/tides
Click SAVE and then try calling. For more information, Twilio's website has many more
examples of how to interface with their servers using either their REST API or TwiML.