google-voice-call.py Source

#!/usr/bin/env python
'''
    A ugly script to pretend that Google Voice has an API for calling out.
'''
import sys, os, re
import urllib, httplib2
from os import path
from simplejson import load
from BeautifulSoup import BeautifulSoup
def main():
    if not path.exists(path.join(
                        path.expanduser('~'),
                        '.gvoice_auth')):
        return """
You need to create a config file in your home directory\
called '.gvoice_auth' with your Google Account's credentials.\
"""
    else:
        creds = load(open(path.join(path.expanduser('~'),'.gvoice_auth')))
    if len(sys.argv) == 2:
        fromnum = creds['default_from']
        tonum = sys.argv[1]
    elif len(sys.argv) == 3:
        fromnum = sys.argv[2]
        tonum = sys.argv[1]
    else:
        return "Invalid number of arguments\nUsage: %s <number> from_number]" % sys.argv[0]
    auth_tok = authenticate(creds['user'], creds['passwd'], 'grandcentral')
    r = call(tonum, fromnum, auth_tok)
    print "Call request returned: ", r
        
def call(number, fromnum, auth):
    data = {
        'outgoingNumber': number,
        'forwardingNumber': fromnum,
        'remember': 0,
        }
    main_uri = "https://www.google.com/voice"
    call_uri = "https://www.google.com/voice/call/connect/"
    headers = { 'Content-Type': 'application/x-www-form-urlencoded',
                'Cookie': 'gv=%s' % auth }
    h = httplib2.Http()
    response, content = h.request(main_uri, 'GET', headers=headers)
    if not response['status'].startswith('2'):
        raise Exception(response['status'] + ': ' + content)
    soup = BeautifulSoup(content)
    _rnr_se = soup.find('input', attrs={'name':'_rnr_se'})
    data['_rnr_se'] = _rnr_se['value']
    response, content = h.request(call_uri, 'POST', body=urllib.urlencode(data),
                                  headers=headers)
    if response['status'].startswith('2'):
        return content
    else:
        raise Exception(response['status'] + ': ' + content)
def authenticate(user, passwd, service):
    '''
        Basic perform ClientLogin method of authenticating a Google Account.
        Returns the Auth=... bit required in the Authorization header.
    '''
    h = httplib2.Http()
    uri = 'https://www.google.com/accounts/ClientLogin'
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    request = urllib.urlencode({
        'Email': user,
        'Passwd': passwd,
        'service': service,
        })
    response, content = h.request(uri, 'POST', body=request, headers=headers)
    if response['status'] == '200':
        return re.search('Auth=(\S*)', content).group(1).strip()
    else:
        raise Exception(response['status'] + ': ' + content)
if __name__=='__main__':
    sys.exit(main())