twitter feed0xdecafbad.com

Google Voice Command Line Script

by on Jul.28, 2009, under Telephony

UPDATE: Aug-20-2009 I added the ability to use a ~/.netrc file (if Net::Netrc is installed, if its not it will not use that :)   I also fixed the meta following problem.  Fixed a couple other bugs – like the username/pass incorrect not reporting that error properly.  You should upgrade to the new version now.

UPDATE: Sept-10-2009 I added the ability to send calls/sms messages to named contacts.  It will use your google voice contact data, so if you want to use this feature you have to create a contact in google voice and use the nickname that you gave them.  I changed the way arguments are passed, run the program for usage information.  If you were already using this you will have to adjust how you call the program.

I wrote a perl script that lets you interface with your Google Voice account.  You can place a call, cancel a call, and send a SMS message easily.  This is ideal for people that want to send SMS messages for system alerts, or for other reasons.

In order to use this script you must first download it.  Then edit the username, password and default number variables near the top of the script.  Install any missing perl modules based on whatever distribution you have, if you run the script it will tell you what it is missing.  Invalid args or no args will give you a help screen.

To send an SMS message to 12345678

./googlevoice.pl sms 12345678 this is a test sms message

To place a call to 12345678 (optionally set the ‘forwarding number’)

./googlevoice.pl call 12345678

./googlevoice.pl call 12345678 90123456

To cancel a call placed through the web (or this script)

./googlevoice.pl cancel

In the future I may access the HTTP based inbox so  that you can periodically check for messages, and react to triggers on them.  In order to do this you would access the following URLs.  If anyone is bored I will gladly accept patches to my script to add this functionality.

Inbox XML:
https://www.google.com/voice/inbox/recent/inbox/

Starred Calls XML:
https://www.google.com/voice/inbox/recent/starred/

All Calls XML:
https://www.google.com/voice/inbox/recent/all/

Spam XML:
https://www.google.com/voice/inbox/recent/spam/

Trash XML:
https://www.google.com/voice/inbox/recent/trash/

Voicemail XML:
https://www.google.com/voice/inbox/recent/voicemail/

SMS XML:
https://www.google.com/voice/inbox/recent/sms/

Recorded Calls XML:
https://www.google.com/voice/inbox/recent/recorded/

Placed Calls XML:
https://www.google.com/voice/inbox/recent/placed/

Received Calls XML:
https://www.google.com/voice/inbox/recent/received/

Missed Calls XML:
https://www.google.com/voice/inbox/recent/missed/


60 Comments for this entry

  • spif

    I am working on modifying your script to do inbox calls. So far I’ve got the post processing of the raw JSON in a shell script so I need to port it into the perl code. I tried using the perl JSON parser library, but it turns everything into nested hashes that are a pain to deal with, at least for me. I’m also going to set it up to call the Prowl perl client for iPhone push notifications.

  • trixter

    That would be nice. I will integrate your patches if you submit them to me when you are done, or as you get different stages completed.

    I am unfamiliar with prowl, so I do not know what changes it would require. I am sure that there is a way to make that optional for non iphone users.

  • Pablo

    A bug have to be fixed in line 130:

    $rnr_se = uri_escape($1);

    My rnr_se has some especial symbols such as / and + . These have to be translated using the URI escapes.

    Great job.

  • trixter

    Thanks, I added the patch.

  • APNJJJ

    ERROR: Unable to get the rnr_se value
    root@plugcomputer:~#

    :(

  • Peter

    When script submits authentication form Google sends intermediate page which uses a meta refresh, meaning that the destination URL is in a tag, which WWW::Mechanize doesn’t follow. I had to add this line to get it to work:
    $mech->follow_link(tag => ‘meta’); right after line: $mech->click(); in sub auth

    Really nice script :)

  • trixter

    Apnjjj: are you using a non US IP address? I have only seen that if its used from outside the US, since right now its only a US (maybe Canada) offering, google redirects and does not let you login.

  • trixter

    I will add that, but I did not know that it was required. I have not noticed any problems, since the whole point of the authentication is to just get the rnr_se value and set a cookie. Is the rnr_se not getting read as a result? I will add it anyway because I do not think it will harm anything, and it may help some people.

  • Peter

    Actually I’ve setup my Google Voice in US, but right now I’m abroad and that is probably why I get this intermediate page with redirect before the main page loads.
    Before I added this line: $mech->follow_link(tag => ‘meta’); I also got this “ERROR: Unable to get the rnr_se value”
    As you said it shouldn’t cause any problems and will allow to use the script regardless of location.

  • shyft

    I had to comment out $mech->follow_link(tag => ‘meta’); in sub auth for it to work on my box.

    thanks trixter… you have denied me the pleasure of trying to write my own gvsms utility.

    -shyft

  • trixter

    shyft: you can always extend it to support boxes so you can process received SMS messages, automagically deal with voicemails, etc.

    I will work on making that a conditional, it seems some people require it, others dont.

  • trixter

    there should be some fixes in the newest version now. See the update notice at the begining of the post for notes on the new auth method which should make it more multi-user friendly.

  • APNJJJ

    trixter: Yes I am using a Canadian IP address. I have no troubles logging into http://voice.google.com from it. (grandfathered from the grandcentral days)

  • APNJJJ

    works now though with your new version!

  • trixter

    I should have clarified, google voice claims its only available to US/CA. Trying from Europe has caused a redirect and failure to access google voice. I havent tried for a couple weeks, but they were fairly adamant about breaking it (even if you already had an account and were on holiday) for people outside North America (I dont know about Mexico, which technically is part of North America).

  • APNJJJ

    Can anyone confirm that Google Voice effective broke this script? I can’t seem to place any calls anymore, may have something to do with them removing their option of adding a different phone to ring.?

  • trixter

    been sending text messages to Europe all morning and I just placed a call and it went through.

    Maybe it is your account that got closed due to overuse/abuse? Maybe it was a temporary failure? Did you edit the script in any way?

  • Ryan

    What Perl distribution do you recommend so that this runs properly?

  • trixter

    I use the default that comes with eeebuntu. This is perl 5.10. I dont know that it matters, so long as you can install the various modules either from a package manager or via cpan. Are you having a problem with any particular distribution?

  • Ryan

    I’m not confident that I’m installing the modules properly.

    I have 5.10. I’m not sure it matters either. I keep trying to install the additional modules, but I get a message saying it’s “impossible” to install. I figured that was a permissions issue, and trued installing from the root. Still, no dice.

    I used a script along the lines of: cpan -i ; cpan -i ; etc. etc.

    Could you suggest an order to install them?

  • Ryan

    Oooh, I had “modulename1″ and “modulename2″ enclosed in brackets (explaining why they didn’t show up on the last comment) to represent the modules.

  • trixter

    I dont know what is going on. How I do it is either with apt-get when there is a module present or
    perl -MCPAN -e ‘install WWW::Mechanize’

  • Ravenii

    Thanks Trixter,
    This is so great. I am using it on several servers to send me SMS alerts!

  • Mark Waters

    I have tried running the script on Ubuntu 9.04 and Debian 5.0 and get the same error :-

    Can’t call method “url” on an undefined value at /usr/local/share/perl/5.10.0/WWW/Mechanize.pm line 713.

    Any suggestions ?
    Thanks
    Mark Waters

  • trixter

    I use ubuntu 9.04, that is what I developed on. This makes me think that there is a variable that is not set right.

    Can you email me your script (XXX your username and password only but make no other changes to what you have, if you used the .netrc way you dont have to edit it at all) at trixter AT 0xdecafbad.com so that I can see what is going on?

  • Mark Waters

    sorry to be a nuisance , but after clearing everything out of the ~/.netrc file except the specific variables it seems to be working.

    Thanks for your help (and script)
    Mark Waters

  • Jacroe

    Have you put this under a license? I would like to use this in a software project that I hope to release.

  • trixter

    Yes, the script is under the MPL (Mozilla Public License), which will be the first 50 or so lines of the script (comments).

    Basically this means that you cannot make it part of a GPL project, but can LGPL, BSD, MPL, or pretty much anything except GPL.

  • Blue

    Has anyone here tried to integrate this script into asterisk?
    If so, is there a tutorial somewhere I might could read.
    Thanks

  • trixter

    Integrating into asterisk would depend on what you want to do. If for example you wanted to be able to send SMS messages via XMPP/Simple (sip instant messaging) it would not be trivial at all. If you just wanted to send a message, you could use the system command.

    With FreeSWITCH.org, a open source softswitch I think is better than asterisk (higher cps rate, higher concurrent call rate, *fully* RFC compliant SIP stack, TLS/SRTP, and an eventing system that dances circles around asterisk) it would not be that difficult to integrate this into a more unified solution. You would be able to receive a sip instant message, or xmpp (jabber/google talk) and send it off.

  • Blue

    Ok. Thanks for the reply. I got to browsing the code for my setup and figured it out. Just had to make sure all the cpan modules were installed and then modify my extensions_custom.conf. I was using the default pygooglevoice in PiaF distro, and it was giving me trouble. That’s when I found your site. I am looking at trying to squeeze my setup into a WRT54G or most likely a NSLU2. Do you think FreeSWITCH would run on this old 500Mhz P3 I am using now? (i know “where’d you did that outta the trash @)

  • trixter

    yes, FreeSWITCH will run on a system that old. It wont be able to do a lot of traffic, but it will run. FreeSWITCH works natively in windows, linux, osx, bsd, solaris, and others. It has even been ported to Windows CE by at least one person. It will run on the smallest of boxes (within reason) up to telcobridges.com gear.

    When it comes to x86 type systems, if asterisk runs on it, FreeSWITCH will run on it with less cpu utilization at the same call volume.

  • Blue

    Is there somewhere i can get a tutorial or example on how to integrate this script into Freeswitch? I am gonna try freeswitch on my new server. I am trying to setup a couple extensions, sipgate, and Google voice for now.

  • VulK

    this will allow to enable/disable phones:

    ###
    # toggle phone
    ###
    sub togglephone {
    my ($phoneId, $enabled) = @_;
    $cookiejar = HTTP::Cookies->new();

    $rnr_se = auth($cookiejar);

    if (!defined $rnr_se) {
    return;
    } else {
    my ($url, $client, $request, $response, $postdata);

    $client = LWP::UserAgent->new();
    $client->agent(‘Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.11) Gecko/2009060308 Ubuntu/9.04 (jaunty) Firefox/3.0.11′);
    $client->timeout(30);
    $client->cookie_jar($cookiejar);

    $url = ‘https://www.google.com/voice/settings/editDefaultForwarding/';
    $postdata = “phoneId=$phoneId&enabled=$enabled&_rnr_se=$rnr_se”;

    $request = HTTP::Request->new(POST => $url);
    $request->content_type(‘application/x-www-form-urlencoded’);
    $request->content($postdata);
    $response = $client->request($request);

    if ($response->is_success) {
    print “Phone enabled/disabled\n”;
    } else {
    print “Could not enable/disable phone “.$response->status_line.”\n”;
    }
    }
    return;
    }

    phoneId is an integer starting from 1
    enabled is either 0 or 1
    Best

    VulK

  • trixter

    Thanks I will merge this in soon. I plan on refactoring everything and making this a perl module so that it is easier for other people to use in their projects.

  • trixter

    blue: afaik no there is not a tutorial. The way that I can easily see it working is to get a gizmo account (rumor is that google just bought them). Google will route via SIP through gizmo to you. If you see a X-googlevoice: true header then it came from google voice. I may be mistaken on the header itself, but it is something like that.

    It is a bit klugy if you want to use this to place a call, you pick up your phone and dial, then your dialplan does a system call to execute the script and wait for the inbound googlevoice call, then it will do a uuid_bridge or something to bridge the two together. Alternatively you cna use a conference instead.

    If you want to send a sms perhaps from a chat event you would need something that would see the chat event (event socket, lua or javascript etc) and then resend that via this script.

    I have plans to make this a perl module which would make it far easier to make an event socket perl app that would directly send messages and such. I just have been lazy lately.

  • Blue

    when i try to use the script i am getting
    “Could not place the call 500 Internal Server Error” ?
    has something changed?

    Thanks

  • trixter

    it is still working for me. 500 is a google side error, this means that they either got malformed data from you, or they had problems of their own. Are you still experiencing problems? What country is the IP you are connecting to google from?

  • Roland Walker

    blue and trixster

    re 500 Internal Server Error

    google now wants a phoneType parameter, eg phoneType=2, posted to https://www.google.com/voice/call/connect/. Just add this to the $postdata string in subroutine placecall.

  • trixter

    I will have to see if that breaks anything else. I do not have that and its working elsewhere, why I think that its a bit odd that its happening.

    Thanks for the patch though!

  • Blue

    trixster: it was still dying with the 500 error.
    I added the phoneType parameter as Ronald said and it works now.

    What are the values for phoneType? I just used =2 as in the previous post..

    P.S.- I do thank you all for the help.

  • Blue

    on the previous post i forgot to mention calls and IPs are US.

  • bob

    THANK YOU Roland Walker! That phoneType=2 thing saved me a ton of time.

  • Geordie Korper

    I had to do the
    $postdata = “outgoingNumber=$dst_number&forwardingNumber=$from_number&subscriberNumber=undefined&remember=0&_rnr_se=$rnr_se”. “&phoneType=2″;

    modification to get it working again.

    As long as I am posting something I might as well mention that I hacked in support for the Mac OS X keychain instead of using a saved password:

    #
    # OPTION 3
    # Enable use keychain support
    #
    my $use_keychain = 1;

    if ($use_keychain)
    {
    open (KEYCHAINITEM, “security 2>&1 find-generic-password -g -s ‘Google Services’|”);
    while ()
    {
    /”acct”=”(.*)”/ and $username = $1;
    /^password: “(.*)”$/ and $password = $1;
    }
    }

  • Tuga Cari

    Hi there,

    Is there a way to use a proxy when posting to google voice website ?
    If so, could you please point me the direction to achieve this ?

    Thank you!
    Tuga Cari

  • john doe

    is this still in development? i can definitely utilize this script in my scripts! i wish there was a way to pull current inbox translations via an RSS feed.. oh well.

  • trixter

    john doe: my plan is to change this over to a perl module to make it easier to use. I am lazy though and have had other things consuming my time. As for pulling the inbox, I have given the url to get the JSON data, you just have to parse that (something I am open to accepting patches for). I parse some data like the contacts list but that is about it.

  • trixter

    tuga cari: I would have to add code that lets you use a proxy. I have been hesitant to do much with this until I change it over to a perl module making it easier to use in other programs. I have just been lazy lately.

  • trixter

    Geordie: thanks! I will work that in when I redo this as a perl module. until then the code is here for everyone else to get this working :)

    yes I really am being lazy, even about moderating comments. sigh.

  • trixter

    I got the 500 error from a bad password/username. I am going to rework this, I think there is a bug that I fixed in other software that this came from (why I really wrote it, a silly bot on irc) but failed to fix it here because its just so easy to forget about this page.

    I *think* that I failed to properly check for a valid login at one point. I plan on making sure that it all works when I convert it to a perl module, which I am thinking will be in a week or so. That should also make it a lot easier to extend it and to run it in a wider range of programs. It also means that the original program I wrote this for will be ported to use this instead. I may get a little froggy and write a php version suitable for a webpage, but I have not yet decided on that.

4 Trackbacks / Pingbacks for this entry

Leave a Reply

ERROR: si-captcha.php plugin says GD image support not detected in PHP!

Contact your web host and ask them why GD image support is not enabled for PHP.

ERROR: si-captcha.php plugin says imagepng function not detected in PHP!

Contact your web host and ask them why imagepng function is not enabled for PHP.

ERROR: si-captcha.php plugin says GD image support not detected in PHP!

Contact your web host and ask them why GD image support is not enabled for PHP.

ERROR: si-captcha.php plugin says imagepng function not detected in PHP!

Contact your web host and ask them why imagepng function is not enabled for PHP.

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!