Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2012/02/14

Simple Telephony Tool with Twilo

As long-time readers of this blog might know, I'm a command-line guy, and for any given technology I start to play with, I like to have a command-line tool. And once Scott W. pointed me to Twilio, I had to go that way.

The good thing about that methodology is that it takes the part that you want to find out and combines it with stuff you pretty much know well. Because there's a lot of PHP in the Twilio documentation, I went with PHP for the project this weekend, but now that I had a moment to take a step back, I stepped to my preferred methods for this, and came up with call_me.pl.

#!/usr/bin/perl

# A simple command-line tool for making a telephone call

use 5.010 ;
use strict ;
use Carp ;
use IO::Interactive qw{ interactive } ;
use URI::Escape ;
use WWW::Twilio::API ;
use YAML qw{ LoadFile } ;

my $twilio_conf = get_twilio_conf() ;

my $status = join ' ', @ARGV ;
if ( length $status < 1 ) {
    while ( <stdin> ) {
        $status .= $_ ;
        }
    chomp $status ;
    }

if ( length $status < 1 ) {
    say { interactive } 'No content' ;
    say { interactive } length $status ;
    exit ;
    }

my $twilio = WWW::Twilio::API->new(
    AccountSid => $twilio_conf->account_sid ,
    AuthToken  => $twilio_conf->auth_token ,
    ) ;

my $url = $twilio_conf->url . uri_escape( $status ) ;

my $from     = $twilio_conf->from ;
my $to       = $twilio_conf->to ;
my $response = $twilio->POST(
    'Calls',
    From => $from,
    To   => $to,
    Url  => $url,
    ) ;

say { interactive } $status ;

exit ;

#========= ========= ========= ========= ========= ========= =========

sub get_twilio_conf{
    my  $twilio_conf = $ENV{HOME} . '/.twilio.conf' ;
    my  $config ;
    if ( defined $twilio_conf && -f $twilio_conf ) {
        $config = LoadFile( $twilio_conf ) ;
        }
    else {
        croak 'No configuration file' ;
        }
    return $config ;
    }

Now, for a few notes of explanation.

First, the modules. I use Carp for error handling, IO::Interactive to allow output when used interactively, but hide it when put into a batch or crontab. URI::Escape is used to turn the message into something query-string-ready, because the way Twilio calls work is that this call interface points Twilio to a web page that handles the actual interaction of the call. And, I'm trying YAML so I don't have to parse the configuration file myself.

To make a call, you need an auth token and account SID from Twilio, plus you need a number. You can use the sandbox number, but then you need to put in a code to make the call work, so you need to get a number from Twilio, too. I put the message URL and the number to call into the YAML, too, because I wanted to have the same connect-it-all-via-pipes method I use for twitter.pl and facebook.pl to be at work here. If your use case is calling all the server guys if there's a power outage to the server room, you will want to pull the number from somewhere else.

As I mentioned, you need a web-available TwiML application to define the interaction. In my case, it looks like this:

<?php
    header( "content-type: text/xml" ) ;
    echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ;
    ?>
<Response>
    <Pause length="3" />
    <Say language="en" voice="woman">
       <?php echo $_GET['message'] ; ?>
    </Say>
</Response>

As mentioned, I did the work over the weekend overwhelmingly in PHP, and this is very much based on that work.

Twilio has an XML format that determines how phone conversations are handled, with enough hooks that I can easily see how you could implement a voicemail system, an extensive phone tree, or a song-of-the-day setup. I don't have that here. Right now, what I'm seeing is a tool to find my phone when I don't have another one to call it, or a way to have my phone tell me when a long-running process ends, or even a for-me wake-up call setup. Twilio also can do SMS, which is what most of my coding this weekend was around. SMS works over phone, not IP, so it should still be able to tell me things when I have my 3G shut down to save battery life. So, as a user and not a business, I guess I'm starting to see some practical uses for  this stuff.

I will have this up on Github before too long. If you have ideas about what you could do with Twilio, I would be glad to hear it.