2010.04.06
Identifrac Reloaded
This is neat: Gerd Riesselmann pulled the source for my abandoned Identifrac project out of archive.org (!) and adapted it for inclusion in his Gyro-PHP framework. It's also usable as a stand-alone class. Check out his blog post for more info and documentation.
2010.04.03
List of Asimovian Robots with Serial Numbers
An interesting convention in Isaac Asimov's Robot series was to give some robotic characters a human nickname based on their model identifier. I was unable to locate a comprehensive list of these characters, so I attempted to compile my own. I'm sure it's incomplete, but perhaps you will find it useful nonetheless. Corrections welcome.
| Series | Nickname | Featured In |
|---|---|---|
| AL | Al | Robot AL-76 Goes Astray |
| DV | Dave | Catch That Rabbit |
| EZ | Easy | Galley Slave |
| HRB | Herbie | Liar! |
| JG | George | —That Thou art Mindful of Him |
| JN | Jane | Feminine Intuition |
| LNE | Lenny | Lenny |
| LVX | Elvex | Robot Dreams |
| NDR | Andrew | The Bicentennial Man |
| NS | Nestor | Little Lost Robot |
| QT | Cutie | Reason |
| RB | Robbie | Robbie |
| SPD | Speedy | Runaround |
| TN | Tony | Satisfaction Guaranteed |
I haven't had a lot of time to work on side projects recently, but I've had my eye on Twilio's service for a while. They provide a pay-as-you-go RESTful API for telephony, enabling applications to send and receive phone calls and (as of today) SMS messages.
This is exciting stuff, and I just had to get my hands dirty. Turns out it's dead simple. Let's walk through building a simple application I call The Message.
Concept
The Message is essentially a voice mailbox, except that it stores a single recording that anyone can access or overwrite. The ideal workflow goes something like this:
- The Message is played back to the user
- The user is prompted to overwrite The Message
- If they choose to overwrite The Message
- Record a new Message
- Go back to the beginning
- Hang up
A Simple Conversation
Twilio works by requesting a URL you specify when it receives a phone call. It passes along some useful metadata -- the caller's geographical location, the call duration, etc. -- along with any interactivity information the user provided over the course of the call. You can use this information to dynamically generate an XML response, in which you can request data like keypresses or an audio recording.
To start, let's just throw up a static file with a response:
<?xml version="1.0" encoding="UTF-8"?> <Response> <Say voice="woman">Thanks for calling The Message. Goodbye.</Say> </Response>
Point your Twilio number at this file and you're good to go. Seriously, that's it. It's not useful as is, but I'm sure you already see the potential.
As an aside, if you've got static text in your Say, you're better off using the Play verb, which accepts a URL to an audio resource in the body. A prerecorded human voice is much more user-friendly than text-to-speech. For the sake of transparency, we'll stick with Say.
The above document is totally devoid of interaction, since the call is ended after Twilio reaches the end of the response. If you wanted to request a recording, use the Record verb:
<?xml version="1.0" encoding="UTF-8"?> <Response> <Say>Thanks for calling The Message. Please record a message after the tone.</Say> <Record action="http://www.example.com/path/to/next-response.php" maxLength="10" /> <Say>No recording has been made. Goodbye.</Say> </Response>
Twilio dutifully records up to ten seconds of audio and POSTs a URL to the script specified in the action attribute (defaulting to the current URL). If Record yields silence, Twilio falls through to the next verb, an error message in this case.
You can handle the recording URL however you like, or you can do something infuriating such as this:
<?xml version="1.0" encoding="UTF-8"?> <Response> <Say>Thank you. Your message has been discarded.</Say> <Play>http://www.example.com/media/sad-trombone.mp3</Play> <Say>Goodbye.</Say> </Response>
Yes. Spectacular.
Building The Message
Being useless and irritating users is all well and good, but in our real application, we'll need to retain the URL of the recording somehow. A flat file would probably be sufficient, but I'd like to keep some metadata as well, so I used a SQLite database.
First we'll pull up our trusty terminal and set up a new database with one table:
$ echo "CREATE TABLE messages (id INTEGER PRIMARY KEY, url TEXT, timestamp DATE);" | sqlite3 themessage.db
And finally, the script itself, which generates some Response XML. The contents vary depending on the values in the $_REQUEST superglobal:
<?php
$db = new PDO('sqlite:/srv/www/jessedubay.com/p/twilio/themessage/db/themessage.db');
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
echo "<Response>\n";
if (!empty($_REQUEST['RecordingUrl']))
{
// They supplied us with a recording, overwriting The Message
// Insert the new URL into the database
$stmt = $db->prepare("INSERT INTO messages (url, timestamp) VALUES (:url, DATETIME('now'))");
$stmt->bindValue(':url', $_REQUEST['RecordingUrl'], PDO::PARAM_STR);
if(!$stmt->execute())
{
// Speak an error if the write failed for some reason
echo "\t<Say>The message was heard, but it was not saved. Sorry.</Say>\n";
}
}
else if(!empty($_REQUEST['Digits']))
{
// They did not supply us with a recording, but did supply us with digits
// This means they wish to overwrite the message
echo "\t<Say>At the tone, record a new ten second message.</Say>\n";
echo "\t<Say>Stop talking or press any key to stop recording.</Say>\n";
echo "\t<Record maxLength=\"10\" />\n";
// If the user is silent, the Record verb falls through
echo "\t<Say>You did not change the message.</Say>\n";
}
// Retrieve the current message if possible
$result = $db->query('SELECT url FROM messages ORDER BY timestamp DESC');
$url = ($result !== false) ? strval($result->fetchColumn()) : '';
if(empty($url))
{
echo "\t<Say>There is no message.</Say>\n";
echo "\t<Say>Press any key to create the message.</Say>\n";
}
else
{
echo "\t<Say>The message is:</Say>\n";
echo "\t<Play>" . htmlentities($url) . "</Play>\n";
echo "\t<Say>Press any key to overwrite the message.</Say>\n";
}
echo "\t<Gather numDigits=\"1\" />\n";
echo "\t<Say>Goodbye.</Say>\n";
echo "</Response>";
?>
Fifty-odd lines of procedural logic later, we have a working prototype. In the real world, you'd want to use hmac_hash() to ensure that the request is actually coming from Twilio, and there's the potential for database concurrency weirdness, but for an hour's worth of R&D I'd say this is incredibly impressive.
We've just scratched the surface with this project; Twilio also does transcription, conference calls, dialing/transfers, and SMS messages, as mentioned, and it's all as easy to get going as you've seen here. They also give trial accounts a $30 balance to play with, so you ought to give it a try and consider adding telephony to your application -- better yet, come up with something totally new and let me into your beta. :)
Further Reading
- Twilio's How It Works page describes the programmatic flow of a call well
- and the Documentation is pretty great too
2010.01.22
Quotation
One of the things you'll discover as you learn more about macros is how much day-to-day coding in other languages consists of manually generating macroexpansions. Conversely, one of the most important elements of learning to think like a Lisp programmer is to cultivate a dissatisfaction with repetitive code. When there are patterns in source code, the response should not be to enshrine them in a list of "best practices," or to find an IDE that can generate them. Patterns in your code mean you're doing something wrong. You should write the macro that will generate them and call that instead.
2009.12.30
Swapping Caps Lock and Escape
Caps Lock is almost certainly the most useless function of my keyboard. This combined with the placement and size of the key make it perfect for rebinding.
I spend a lot of time in vim, so rather than restoring the Control key to its rightful glory, I opted to swap Escape and Caps Lock -- GNOME makes this very easy.
It's saved me quite a bit of unneeded motion, and has become such a habit that I found the need to do the same in Windows. KeyTweak is a great utility that works on the common versions, and can do much more elaborate remapping if you desire.
Now if I can just ween myself off of the arrow keys and start using HJKL consistently, I'll be set!
