Archive for August, 2010

How to build an automated Twitter bot using JavaScript and Tropo

Friday, August 13th, 2010

We’re back with more how-to goodness!  While perusing our relatively extensive blogging history and existing documentation, we noticed the previous examples showing how to link Twitter and Tropo were moderately complex and potentially daunting, especially for someone just trying to get an initial feel for how it works.  So, in an attempt to remedy that, we endeavored to provide an easy, all-inclusive example from start to finish.  Hopefully we succeeded.

Our example today is a simple RSVP Twitter Bot; when someone tweets the Twitter account attached to your application, it responds back automatically with a confirmation indicating their RSVP was received.   In this case, we set it up to be password driven; if the application receives the Tweet “Tropo Rocks!”, it responds with an approval message.  Any other message will cause the Twitter bot to respond with a message indicating they sent the wrong password and to try again.

We’ll assume you have a Tropo account at this point and begin with creating your Twitter app.  If you don’t already have a account, you can click here to create one.

1) Login to your Tropo account, then go to Your Applications and click the Create New Application link:

2) Choose Tropo Scripting; this will bring up the New Application window:

3) Give the application a name; we chose ClubTropo to fit the example, but you can use whatever you’d like.  Next, click the link for Hosted File (next to What URL powers your app?) and choose Create a new hosted file for this application.  This will open the New Mapped File window:

4) You will need to give the file a name; as with the application name, it can be anything you like, but make sure this one ends with .js to identify it as Javascript .  In the box for File Text, enter in the following simple code:

message = currentCall.initialText;
if(message == "Tropo Rocks!"){
    say("You just learned how to make a Twitter bot with @Tropo for free!  Welcome to the club.");
}
else {
    say ("Say what?  Try it again - send us a tweet with the correct password to get on the list.");
}

Then click Create File to save it.

To explain what the code does:

  • We define the variable message as currentCall.initialText, which contains the tweet sent by the user (go here for more on currentCall).
  • Next, we specify what to tweet back if the user’s tweet has the correct message (i.e., Tropo Rocks!) and when it does not.
  • That’s it!  That’s all the code you need.

5) Once the file has been created and you’re back on the New Application screen, you’ll see the path to your file has been automatically filled in for you.  Now click Create Application to save the application as a whole:

6) This will bring up the page in the next screenshot.  Here, we need to add our Twitter account to the application; this will be the Twitter account that will act as the bot.  Select the Twitter icon at the bottom of the screen and you’ll see a link that says Click to activate Twitter.  This will attempt to connect to whatever Twitter account you’re currently logged into, so make sure you’re in the right one before you click the link.

7) Twitter will display a webpage in your browser asking you to Deny or Allow Tropo access to your Twitter account.  If you’re definitely in the right account, go ahead and click Allow:

8) You will then return back to the Tropo New Application screen and your Twitter account name will be listed:

9) Click the Update Application button to save the change, and you’re ready to test!  Our Twitter bot is named ClubTropo and we sent it a message from two different accounts.  From TropoUser, we sent “@ClubTropo Tropo Rules!”, which was rejected.  From JD_Gryph, we sent “@ClubTropo Tropo Rocks!”, which was accepted as the correct password.  Check out the responses below:

Voila!  RSVP Twitter Bot achieved.  Feel free to test with @ClubTropo and/or create your own; the door is wide open!

For more information, check out our Tropo Scripting documentation, or check out our Tutorials and Samples.

(Sidenote:  You may want to check out this blogpost before testing any Twitter apps; Twitter can be touchy with multiple instances of identical messages)

FoneFindr uses Python, Tropo Scripting, and Google App Engine to scale.

Thursday, August 12th, 2010

Phones used to be heavy and attached to the wall. They were hard to lose. Now that phones are portable, they tend to end up in the strangest places. Between couch cushions. Under the seat of the car. In your sock drawer.

Around the world, the phone finding ritual is repeated thousands of times each day: hunt for your phone for a while, realize it’s not in any of the usual places, use another phone to call it and chase the ringer. But what if you don’t have another phone to use?

Fonefindr Screenshot FoneFindr takes a simple idea (“make my phone ring”) and pairs with a little voyeuristic fun for a huge impact. Visit the site, punch in your phone number, and using Tropo, FoneFindr makes your phone ring. Once you find it you can share where it was found so others can laugh along with you. You can even leave a message that will be displayed on the site for anyone to listen to. Sort of like Texts From Last Night, but for wayward phones.

FoneFindr was originally built on another voice platform where it sat happily for a few days. Then it went viral. It was featured on the productivity blog MakeUseOf, Google’s App Gallery, and StumbleUpon. Within hours, tens of thousands of people had tried FoneFindr and they needed to scale and needed to do it fast.

FoneFindr is running on Google App Engine, and we helped them offload some of their processing from the web server to our purpose-built voice cloud. Using Tropo’s scripting platform and Python, we quickly helped FoneFindr re-write their telephony features to run on Tropo. Instead of processing the voice calls on AppEngine, the whole call takes place on Tropo. The web site sends a simple GET request to their Tropo application, and Tropo makes the call, plays the audio and records and transcodes any messages the phone’s owner decides to leave. Those recordings are then sent back to the web application on App Engine.

This allows his App Engine instance to use far less processing power and reduces back and forth traffic to the server. So not only does his telephony app scale better now, but his web app does, too. Total time from when he called us for help to deploying the new version of the site was less than two hours.

Does your voice platform scale? Maybe you should try the voice cloud that’s built by telephony experts.

How to Send & Receive SMS Text Messages Using Tropo and Ruby

Monday, August 9th, 2010

Tropo users come from all ranges of experience, both with coding in general and coding in the languages we support. With that in mind, we put together a simple, step-by-step guide for Tropo that will get you from the moment you first sign up for Tropo, all the way to the actual sending and receipt of a text message.  It’s not fancy, but that’s the point – to provide you with the foundation to build bigger and better applications moving forward.  So, without further ado, we happily present:

The 7 Steps to Text Success

1) First step, as always, is to login.  If you don’t already have a Tropo account, you can register for free at http://www.tropo.com/account/register.jsp and your login credentials will be e-mailed to you.  Once you have your credentials, click the Login link at the top right of the main Tropo site (tropo.com) and enter them in.  Now that you’re logged in, click on the Your Applications quick link:

2) Next, click on the Tropo Scripting icon; if you already have applications created, you’ll need to click the Create New Application link first.  This will open the New Application window:

3) Provide the application with a name; we used TextDemo, but it can be whatever you like.  Next, click the link for Hosted File (next to What URL powers your app?), then click Create a new hosted file for this application.  This will open up the following window:

4) Enter in a File Name – make sure it ends with .rb to identify it as a Ruby application – then for the File Text, enter this short script:

                      answer
                      say 'Hello World! Thanks for the text.'
                      hangup

5) Click Create File to save it, then when you’re returned to the New Application page, click the Create Application button to save the entire app.  You should now see this page:

6) Click on the Add a new phone number link to get a standard phone number assigned (for free), then give it a few minutes to allow your application to propagate to our servers.

7) With your new app created and a phone number assigned, you’re ready to test! Send a text to the number, any text, and you should immediately receive the response “Hello World!  Thanks for the text.”

That’s it!  You now have a working SMS application in its simplest form.  This should just be the beginning, though; the potential power of Tropo extends far beyond Hello World apps.  Take a look at our Scripting documentation, our Tutorials and our Samples for inspiration, and let us know what you come up with!

Countdown to Doomsday

Tuesday, August 3rd, 2010

By now, everyone has heard about the impending Mayan-prophesized apocalypse looming just over the horizon; December 21th, 2012 is getting closer everyday, and the media hype surrounding it shows no sign of slowing down.  Now while the mainstream and not-so-mainstream media has a fantastic track record when it comes to end of the world predictions (Y2K WILL BE THE DEATH OF US ALL, oh wait…), we figured we better take this one seriously since they made a whole movie about it and all.  Instead of maxing out the credit cards and going on a two year Vegas bender, we decided to be altruistic instead and help our fellow man develop their own Personal Catastrophe Planning Timeline™, or PCPT for short.

What’s the first thing you need to know to plan a timeline?  How much time you have left, of course!  So, in the spirit of panicked hyperbole that inspired NASA to write an entire FAQ about 2012, we present the 2012 Doomsday Countdown, a Tropo Scripting application written in Ruby that counts down the days, hours, minutes and seconds until midnight, December 21st, 2012!

To test it out, either call (407) 374-9941 using a standard phone, sip:9991443444@sip.tropo.com if you want to use a softphone, or +99000936 9991443444 if you want to give it a shot over Skype.

Want to see the code and how it was built?  The full code can be found here on Github; we know it looks a bit complex, so we’ll also break it down for you, piece by piece.

The first two sections of the application, labeled TIME_ZONE_HASH and TIME_ZONE_NAME, assign a timezone name to each area code in order to define their GMT offset (-4 for the East Coast of the United States during Daylight Savings Time, for example); we need to find this value because the Tropo server is set to GMT.  Without it, everyone would get a countdown a few hours off (unless you happen to live in Greenwich, England).

The area code matchup won’t be flawless, as some area codes cross timezones and we didn’t go six digits deep on the phone number, but it should fit for 99% of people.  You could feasibly extract this same area code/timezone information from a database or a web service as well; for ease of clarity, we just went ahead and hand coded it this time.

TIME_ZONE_HASH = {'242'=>'atlantic',...,'971'=>'pacific',...,'907'=>'alaskan',...,'808'=>'huh why e'}

TIME_ZONE_NAME = { 'atlantic' => { :gmt_offset => 3 },
                   'eastern'  => { :gmt_offset => 4 },
                   'central'  => { :gmt_offset => 5 },
                   'mountain' => { :gmt_offset => 6 },
                   'pacific'  => { :gmt_offset => 7 },
                   'alaskan'  => { :gmt_offset => 8 },
                   'huh why e' => { :gmt_offset => 9 } } 

The second portion labeled DEFAULT_OPTIONS determines the statements for a BadChoice (like saying ‘maybe’ instead of ‘yes’ or ‘no’), or a Timeout.  It attempts to get valid input twice for either event, and has a unique statement for each attempt (defined by ‘when 1′ for first attempt and ‘when 2′ for second attempt).


DEFAULT_OPTIONS = {
    :attempts    => 2,
    :timeout     => 15,
    :voice       => VOICE,
    :onBadChoice => lambda { |event|

        case event.attempt
        when 1
            say "Sorry, didn't catch that. This time in English.", { :voice => VOICE }
        when 2
            say "Sorry, I still don't understand. Please give us a call back if you're still alive.", { :voice => VOICE }
            hangup
        end

    },
    :onTimeout    => lambda { |event|

        case event.attempt
        when 1
            say "Sorry, couldn't hear you. Let's try that again, this time with more spirit!", { :voice => VOICE }
        when 2
            say "Sorry, still couldn't hear you. Please give us a call back if you're still alive.", { :voice => VOICE }
            hangup
        end

    }
}

The next portion calculates the time left between now and doomsday by subtracting today’s date and time (offset by the appropriate hours) from midnight, 12/21/2012.  This returns a value in seconds, which we then convert into days, hours, minutes and seconds using some standard math.

def calculate_time_left(timezone)
    # Set the default to Eastern time if not available
    calculated_time = {}

    # Calculate the difference between now and then
    end_time = Time.local(2012, 12, 21, 0, 0, 0)
    start_time = Time.now - (60*60*TIME_ZONE_NAME[timezone][:gmt_offset])
    difference = end_time - start_time

    #calculating the days, hours, minutes and seconds out of the initial large seconds value generated by 'difference', then dropping the values after the decimal
    calculated_time[:days] = (difference / (60*60*24)).to_i
    days_remainder = (difference % (60*60*24)).to_i
    calculated_time[:hours] = (days_remainder / (60*60)).to_i
    hours_remainder = (days_remainder % (60 * 60)).to_i
    calculated_time[:minutes] = (hours_remainder / 60).to_i
    calculated_time[:seconds] = (hours_remainder % 60).to_i
    calculated_time
end

The next section is where the area code extraction actually occurs (the [0,3] extracts the first three characters of the callerID) and sets ‘eastern’ to be the default timezone if it can’t match up the area code to a timezone:

if TIME_ZONE_HASH[$currentCall.callerID[0,3]]
    timezone = TIME_ZONE_HASH[$currentCall.callerID[0,3]]
else
    unknown_timezone = true
    timezone = 'eastern'
end

Then the actual call flow begins.  We answer the call, ask if you really want to hear the countdown and then either provide you with the days, hours, minutes and seconds if you say ‘yes’ (or press 1), or storm off in a huff if you say ‘no’ (or press 2).  Note there is also a piece in there for people who call from unidentifiable numbers, like Skype:

answer

# Ask if they want to hear the countdown
options = DEFAULT_OPTIONS.merge!({ :choices => 'yes(yes, 1), no(no,2)' })
result = ask '' + 'Countdown to 2012 activated!  Do you want to know how long you have before disaster strikes?', options
if result.name == 'choice'
    case result.value
    when 'yes'
        calculated_time = calculate_time_left(timezone)
        text = calculated_time[:days].to_s + 'days, ' +
               calculated_time[:hours].to_s + 'hours, ' +
               calculated_time[:minutes].to_s + 'minutes and, ' +
               calculated_time[:seconds].to_s + 'seconds '

        if unknown_timezone
            text += 'eastern time. Since we couldn\'t figure out your timezone based on your phone number, we picked eastern time.'
        else
            text += timezone + ' time.'
        end

        say text, { :voice => VOICE }
    when 'no'
        say 'Fine, I didn\'t want to tell you anyways.', { :voice => VOICE }
        hangup
        abort
    end
end

Here we loop a section asking if you want to hear the countdown in a different time zone – you can ask for a new timezone as many times as you like, it keeps going until you say no, at which point we offer our condolences and hangup:

loop do

    # Ask if they want to hear based on a different timezone
    options = DEFAULT_OPTIONS.merge!({ :choices => 'yes(yes, 1), no(no,2)' })
    result = ask '' + 'Would you like to hear the countdown using a different time zone?', options
    if result.name == 'choice'
        case result.value
        when 'yes'
            ask 'Okay then.', { :voice=> VOICE }
        when 'no'
            say 'I don\'t blame you.  Keep your head up, you poor soul.', { :voice => VOICE }
            hangup
            abort
        end
    end

    # Ask the timezone they want to hear it from
    options = DEFAULT_OPTIONS.merge!({ :choices => 'atlantic, eastern, central, mountain, pacific, alaskan, huh why e' })
    result = ask '' + 'Which time zone would you prefer? Please say atlantic, eastern, central, mountain, pacific, alaskan or huh why e.', options
    if result.name == 'choice'
        calculated_time = calculate_time_left(result.value)

        say calculated_time[:days].to_s    + 'days,' +
            calculated_time[:hours].to_s   + 'hours,' +
            calculated_time[:minutes].to_s + 'minutes and,' +
            calculated_time[:seconds].to_s + 'seconds' +
            result.value + ' time.', { :voice => VOICE }
    end

end

hangup

All of this presented to you in our cheery British voice, Simon, defined by this line at the very beginning of the app:

VOICE = 'simon' 

And that’s it – a fancy, friendly doomsday timer, helping you keep track of the exact amount of time you have left to live it up!  Hopefully this app enables everyone to appropriately plot out their Personal Catastrophe Planning Timeline™… remember, wanton hedonism is at least as important as making amends for past wrongs.

Questions, concerns, compliments?  Send em all to support@tropo.com!