/twilio-in-ten-minutes

Create and deploy a Twilio Interactive Voice Prompt System with Ruby, Rails and Heroku in Ten minutes.

Primary LanguageRuby

Awesome IVR!

Twilio IVR Development Framework

This project includes a few parts: a gem for generating TWML (Twilio’s markup language); a modified Newflow; and an IVR Workflow base class.

Prerequisits

You have PostgreSQL installed and have administrative access.

To render the workflows you will need to have GraphViz installed (the dot tool is required).

You have signed up for Twilio and Heroku (see An Interactive Voice Response System in 10 Minutes for a walk through of signing up for these services).

Installation

The project was developed to be deployed to Heroku. Because of this, it makes use of a postgres database. To initialize your database, install PostgreSQL and perform the the following grants (also found in the pg-grants.psql file):

create role twilio with createdb login encrypted password 'tw9987$$5';

create database twilio_app_development with owner=twilio encoding='UTF8' template template0;
create database twilio_app_test        with owner=twilio encoding='UTF8' template template0;

grant all privileges on database twilio_app_development to twilio;
grant all privileges on database twilio_app_test        to twilio;

Configuration

The system should fail to initialize unless config/twilio.yml exists. You must create this file and include your Twilio configuration into the file. It follows the same format as other Rails configuration files, being broken out by the Rails environment (development, test, staging, and production).

NB: DO NOT PUBLISH THIS FIILE! It will contain information about your Twilio account that allows the framework to interact with your twilio accoun. As such you should keep it private.

An example is provided here:

development:
  account_sid:      "'Account SID' from https://www.twilio.com/user/account/"
  auth_token:       "'Auth Token' from https://www.twilio.com/user/account/"
  base_url:         "https://api.twilio.com/2010-04-01"
  ivr_phone_number: "'Number' from https://www.twilio.com/user/account/"
  sandbox_pin:      "'PIN' from https://www.twilio.com/user/account/"

test:
  account_sid:      "'Account SID' from https://www.twilio.com/user/account/"
  auth_token:       "'Auth Token' from https://www.twilio.com/user/account/"
  base_url:         "https://api.twilio.com/2010-04-01"
  ivr_phone_number: "'Number' from https://www.twilio.com/user/account/"
  sandbox_pin:      "'PIN' from https://www.twilio.com/user/account/"

staging:
  account_sid:      "'Account SID' from https://www.twilio.com/user/account/"
  auth_token:       "'Auth Token' from https://www.twilio.com/user/account/"
  base_url:         "https://api.twilio.com/2010-04-01"
  ivr_phone_number: "'Number' from https://www.twilio.com/user/account/"
  sandbox_pin:      "'PIN' from https://www.twilio.com/user/account/"

production:
  account_sid:      "'Account SID' from https://www.twilio.com/user/account/"
  auth_token:       "'Auth Token' from https://www.twilio.com/user/account/"
  base_url:         "https://api.twilio.com/2010-04-01"
  ivr_phone_number: "'Number' from https://www.twilio.com/user/account/"
  sandbox_pin:      "'PIN' from https://www.twilio.com/user/account/"


Heroku

When you deploy to Heroku they will create a database and set the configuration for your dyno.

Once you’ve allocated your Heroku instance, not your application’s hostname for when you configure Twilio.

Twilio

In your dashboard, fill in the ‘Voice URL’ box with your Heroku applicaiton’s URL followed by /workflow/CCard. This will configure Twilio to use the sample credit card activaiton flow when you call your sandbox phone number.

Components

TWML Gem

This gem provides an internal DSL for Ruby for generating Twillio Markup Language. See the file app/ivr_workflows/ccard.rb, or the spec tests in twml/spec for examples of using the TWML gem.

gather

Parameter Description
:numDigits The number of digits to allow for input.
:timeout The number of seconds to wait for the caller to complete their input.

Used for gathering input from the caller. gather statemens may be cut short by user in put. If you put one or more say statements in a gather block, any input will cut them short, while say statements outside of a gather will complete before input is taken.

say

Used to invoke Twilio’s speech synthesizer to talk to the caller.

hangup

Terminates the phone call.

Newflow Gem

The gem has been customized to allow states to transition to themselves while still executing triggers.

Ivrflow

Implement your workflow as you would with Newflow, declaring the states, transitions, predicates and triggers. The Ivrflow base class and the workflow_controller will handle managing the state of your workflow in the database. For each state you declare, you can either implement a #{state_name}_message method, or declare a message block using the DSL:

class MyFlow < Ivrflow
  define_workflow do
    state :start, :start => true do
      transitions_to :stop, :if :pressed_1?
      transitions_to :stop, :if :not_pressed_1?
    end
    state :stop, :stop => true
  end

  message :start do
    gather(:numDigits => 1, :timeout => 10) do
      say "Hello there, press 1 or 2 please."
    end
  end

  message :stop do
    say "Thanks for calling!"
    hangup
  end
end

Method Missing or Automatic Methods

pressed_(digits)?

Used to test if the user has entered a specific set of digits, eg: pressed_1?, pressed_10?

not_(predicate)?

This form will invert the logic (convenient for trigger functions) of any method that your worklfow supports. Eg: not_pressed_1?

(state_name)_message

If you don’t declare the message for a state using the message declaration, the framework will look for and call a method composed of the name of the state plus a _message suffix.

Developing Workflows : Ivrflow

Testing

Ineractive Testing Uisng the Web Console

Visit your application’s root / and you should see a list of the registered workflows in the top left. Clicking on a workflow name will bring up a console that allows you to interact with the workflow.

Cucumber

Your IVR Workflows may be tested via the Cucumber BDD testing tool. The framework has been extended to support calling into the IVR application framework. Please have a look at features/ccard.feature for an example of how to write test for your workflow.

Spying on Sessions with the Web Console

Rendering the Workflows

To render the workflows you will need to have GraphViz installed, then execute: rake ivr:render_workflows

Developing / Hacking

Create a local branch that you will_not_push to a public repo, this branch will contain your config/twilio.yml.

Create your config/twilio.yml. Add it to git, check it in.

Push your branch to Heroku as the master.

user@host: ~/projects/twilio-in-ten-minutes $ git checkout -b twilio-deploy
user@host: ~/projects/twilio-in-ten-minutes $ vi config/twilio.yml
user@host: ~/projects/twilio-in-ten-minutes $ git add config/twilio.yml
user@host: ~/projects/twilio-in-ten-minutes $ git ci -m 'my twilio config'
user@host: ~/projects/twilio-in-ten-minutes $ git push heroku twilio-deploy:master

When you’re done, re-checkout master and do your development there. Then to
deploy, checkout twilio-deploy, merge master into it and push to Heroku
again.

This will keep your config/twilio.yml out of the master branch – which is key
for me since it has my Twilio credentails and my master branch gets pushed to
Github (which is probably where you’re reading this).

Other Services

Telephony

Voice and SMS.

Voice, SMS, IM and Twitter integration.