Simple python script that automates the Google Voice web interface to make outgoing calls. Requires httplib2, simplejson, and BeautifulSoup
This script is not tested on Windows but should work, it looks for a file in the users home directory named .gvoice_auth to determine the credentials to use and the default number to use for the 'from' leg of the call. The file is a JSON encoded object with the following attributes:
For example:
{'user':'me@gmail.com', 'passwd':'lamepasswd', 'default_from':'+15855551234'}
Then, simply run the script:
$ python google-voice-call.py 5855551235 Call request returned: {"ok":true,"data":{"code":0}}
Here's the code, though you probably want to grab google-voice-call.py directly, cut and paste can be annoying.
#!/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())