Voice Mashups with Twitter, part 1: Who will win the 2008 SuperBowl? (A mashup in CallXML.)
February 1st, 2008 by Dan YorkWho will win the 2008 SuperBowl this weekend? The Patriots or the Giants? And by how many points will they win?
With those two questions in mind, please call now into one of these numbers using either your regular phone, Skype or a SIP phone:
- 1-617-500-5331
- Skype: +990009369996072341
- SIP: 9996072341@sip.voxeo.net
Once you have answered those two questions, check out:
http://twitter.com/superbowlguess
Ta da… you have just participated in a voice “mashup” between our services and the Twitter micro-blogging platform!
So what’s going on here? At a high level, you called into our servers where an XML document outlined a series of prompts, collected some information and then sent the result over to a Twitter account for posting. (If you aren’t familiar with Twitter, here’s a post I wrote about it.)
There’s obviously a bit more to it (see our Quick Start guide) and over the next few weeks I’m going to explain both what I did and perhaps more importantly how it can be improved! In this part 1 you are seeing a basic call flow with Text-To-Speech prompts. While TTS is fast and, as you will see, extremely easy to create, the voice does sound… well… computer-generated! (Duh!) So in the next installment in this series I’ll talk about adding recorded prompts (and how incredibly simple it is to do through our platform). Future parts to the series will cover such things as better error handling, moving the XML over into VoiceXML/CCXML, adding other content to the output to Twitter, etc.
Naturally by the time this series is done the SuperBowl will long be over and the <deleted> will of course be victorious! However, we’ll just have to come up with some other event for the final script, eh?
Now, if you are impatient and don’t want to wait, your best bet is to head on over to our excellent CallXML documentation to learn what you need to do. Of course, you should also sign up for a free developer account on our Evolution developer site where you can create all of these applications and whatever other apps you can think of related to voice.
Before I start walking through the code, let’s talk about the version of XML I am using. Here at Voxeo we support three different kinds of XML for developing voice applications (as outlined on our Choosing a Platform page): our own CallXML and then the VoiceXML and CCXML standards of the W3C. We created our CallXML first and then have been and continue to be very involved with the development of VoiceXML and CCXML. (For instance, our CTO RJ Auburn chairs the CCXML Working Group within the W3C and Dan Burnett is very active within those groups as well.) We are huge supporters of open standards and are extremely pleased to be leading the industry in terms of compliance with VoiceXML and CCXML standards. As part of this series, I’ll take you on a tour of how those specifications work.
To keep this first post simple, though, I’ve written this first mashup example in CallXML because the code is easier to understand as we walk through it. In a future part, you’ll see how this looks in VoiceXML.
But enough already, let’s dive into the code…
The code starts naturally with a standard XML header and the start of a “do” loop:
<?xml version="1.0" encoding="UTF-8"?> <callxml version="3.0"> <do>> <log>***** STARTING APPLICATION ******</log> <log>***** CALLER ID = $session.callerID; - CALLED # = $session.calledID; *****</log>
With these last two lines I am logging some info primarily for debugging. I also can know how the callers reached us through the Called ID, so I can know if they reached us via a regular phone, Skype or SIP. Next I prompt the caller for the first question:
<prompt label="P1-TeamChoice"
value="Who do you think will win the 2008 superbowl, the Patriots or the Giants?"
choices="patriots, giants"
maxtime="5s">
<on event="choice:patriots"> <assign var="Team" value="Patriots"/> </on>
<on event="choice:giants"> <assign var="Team" value="Giants"/> </on>
<on event="choice:nomatch"><say>That was an invalid choice</say></on>
</prompt>
I will only accept either “patriots” or “giants” as an answer and I put the appropriate text into a variable “Team”. Note that if the caller does not say either choice, the app simply says it was an invalid entry and goes on. It does not reprompt or do any other error checking. (Hint: This will be a future post.) Next I prompt for the second question:
<prompt label="P2-Spread" choices="[NUMBER]"
value="How many points will they win by?" maxtime="5s">
<on event="choice"> <assign var="Spread" value="$session.lastchoice;"/></on>
<on event="maxtime"><say>I'm sorry. You have run out of time to make your choice. Please call again.</say><exit/></on>
</prompt>
</do>
Here I am saying the the choice will be a “[NUMBER]” which lets me accept any “number” and put it into a variable called “Spread”. You’ll note that it writes out the text of the number (i.e. “fourteen” instead of “14″). It also is very liberal with what it accepts. We’ll fix that in a future version.
Now here comes the Twitter integration piece. The Twitter API requires that you send a variable “status” via a HTTP “POST” message, so first, I create a variable called “status” and assemble the text string that includes the team and point spread:
<do label="P3"> <assign var="status" value="The winner will be the $Team; by $Spread; points."/>
Then I send the status variable into Twitter using a <fetch> element:
<fetch var="response" value="http://superbowlguess:password@twitter.com/statuses/update.xml" submit="status" method="post"/>
So this is the “magic” bit. The “var” is just the name of a dummy variable that accepts the XML response back from Twitter. I don’t do anything with this response, but I have to have a variable to accept it. The “value” attribute is the URL (per the Twitter API) that I need to use to send in the status update. Note that I am using the “username:password@URL” construction in order to send in the Twitter username and password for authentication. In the case of the code, the Twitter username is “superbowlguess”. The password for the account is very definitely NOT just the word “password”, but I’m not going to put the actual password here, eh? The “submit” attribute indicates the variable I am sending to the Twitter API and then finally the “method” attribute states that this is sent in via the POST method.
That’s it!
So to do something like this, all you need to do is to get a Twitter account and then create an app like I’ve done and use your username and password in the fetch element. Simple, eh?
I then wrap up the application with a final bit of spoken text and some error catching:
<say>Thank you for guessing the superbowl winner. You can view the results at
twitter.com slash superbowl guess. If you would like to developer applications like
this check out evolution dot voxeo dot com</say>
</do>
<on event="error">
<sendemail from="dyork@voxeo.com"
to="dyork@voxeo.com" type="debug">
We caught an error in our application. Details follow...
</sendemail>
</on>
<on event="onhangup"><exit/></on>
</callxml>
Basically, if there are errors I get an email and if the person hangs up the phone (for instance in the final prompt), the application just exits.
So that’s the code… or at least “part 1″ of the code. In future articles I’ll talk about how this code can be made better and also how it looks in VoiceXML and CCXML.
If you have any questions or comments about this code… suggestions for how it could be done differently (better?)… or any other thoughts I would love to hear them.
Also, if you do something interesting with Twitter integration, please do leave a comment here or email me. I’d love to see what you all will do with it!
Technorati Tags: twitter, callxml, mashups, voice, voicemashups, voip, voicexml, applications
RSS Feed
February 1st, 2008 at 3:52 pm
[...] also kicked off a series on voice mashups and Twitter today with a post “Voice Mashups with Twitter, part 1: Who will win the 2008 SuperBowl? (A mashup in CallXML.) where I show how you can create a voice application that sends its output out to the Twitter [...]
April 21st, 2008 at 11:39 am
[...] able to do this so easily largely because Twitter’s API is so incredibly simple to use, as I discussed in a previous post about Twitter. The full CCXML code is below, but here’s the key part where RJ defined the URL to use to [...]