Class: GoogleVoice::Api

Inherits:
Object
  • Object
show all
Defined in:
lib/googlevoiceapi.rb

Defined Under Namespace

Classes: InvalidLoginException, InvalidPhoneNumberException

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(email = nil, password = nil) ⇒ Api

Create a basic Mechanize agent, initial our objects, and create our dynamic <function>_xml methods



21
22
23
24
25
26
27
28
29
30
# File 'lib/googlevoiceapi.rb', line 21

def initialize(email=nil, password=nil)
  @agent = WWW::Mechanize.new { |agent| agent.user_agent_alias = 'Mac Safari' }
  @coder = HTMLEntities.new
  @email = email if !email.nil?
  @password = password if !password.nil?
  
  # The methods created with this are used to fetch various
  # XML data from Google for call-related history data.
  init_xml_methods()
end

Instance Attribute Details

#agentObject

Returns the value of attribute agent.



14
15
16
# File 'lib/googlevoiceapi.rb', line 14

def agent
  @agent
end

#coderObject

Returns the value of attribute coder.



14
15
16
# File 'lib/googlevoiceapi.rb', line 14

def coder
  @coder
end

#emailObject

Returns the value of attribute email.



14
15
16
# File 'lib/googlevoiceapi.rb', line 14

def email
  @email
end

#passwordObject

Returns the value of attribute password.



14
15
16
# File 'lib/googlevoiceapi.rb', line 14

def password
  @password
end

#rnr_seObject

Returns the value of attribute rnr_se.



14
15
16
# File 'lib/googlevoiceapi.rb', line 14

def rnr_se
  @rnr_se
end

Instance Method Details

#call(remote_number, forwarding_number) ⇒ Object

Place a call to remote_number, and ring back forwarding_number which should be set up on the currently logged in Google Voice account



60
61
62
63
64
65
# File 'lib/googlevoiceapi.rb', line 60

def call(remote_number, forwarding_number)
   unless logged_in?
  remote_number = validate_number(remote_number)
  forwarding_number = validate_number(forwarding_number)
  @agent.post('https://www.google.com/voice/call/connect/', :outgoingNumber => remote_number, :forwardingNumber => forwarding_number, :subscriberNumber => 'undefined', :remember => '0', "_rnr_se" => @rnr_se)
end

#cancelObject

Cancel the call in progress for this account. It does NOT hang up a call that has been answered, only one that has been placed but not completed yet.



70
71
72
73
# File 'lib/googlevoiceapi.rb', line 70

def cancel()
   unless logged_in?
  @agent.post('https://www.google.com/voice/call/cancel/', :outgoingNumber => 'undefined', :forwardingNumber => 'undefined', :cancelType => 'C2C', "_rnr_se" => @rnr_se)      
end

#logged_in?Boolean

Make sure we have a valid Mechanize agent and we obtained the _rnr_se authentication token after logging in. Those are the two keys to determining if we are successfully logged in or not.

Returns:

  • (Boolean)


46
47
48
# File 'lib/googlevoiceapi.rb', line 46

def logged_in?
    (@agent !=nil) && (@rnr_se != nil)
end

#loginObject

Login to a Google Account to use the Google Voice services Most of the calls require a special authentication token called _rnr_se that can be scraped from the page once logged in.



35
36
37
38
39
40
41
# File 'lib/googlevoiceapi.rb', line 35

def ()
  @agent.post("https://www.google.com/accounts/ServiceLoginAuth?service=grandcentral", :Email => @email, :Passwd => @password)
  page = @agent.get('https://www.google.com/voice/')
  dialing_form = page.forms.find { |f| f.has_field?('_rnr_se') }
  raise InvalidLoginException, "Cannot login to Google Voice with #{@email}" unless dialing_form
  @rnr_se = dialing_form.field_with(:name => '_rnr_se').value
end

#sms(remote_number, text_message) ⇒ Object

Send a text message to remote_number



51
52
53
54
55
56
# File 'lib/googlevoiceapi.rb', line 51

def sms(remote_number, text_message)
   unless logged_in?
  remote_number = validate_number(remote_number)
  text_message = @coder.encode(text_message)
  @agent.post('https://www.google.com/voice/sms/send/', :id => '', :phoneNumber => remote_number, :text => text_message, "_rnr_se" => @rnr_se)
end

#validate_number(phone_number) ⇒ Object

International numbers can vary in length as opposed to the standard US 10 digit number So we can’t effectively validate based on length. Instead, let’s make sure we have at least 4 digits and at most 15 since E.164 recommends at most 15 digits minus country code for the phone number (en.wikipedia.org/wiki/E.164)



80
81
82
83
84
# File 'lib/googlevoiceapi.rb', line 80

def validate_number(phone_number)
  phone_number = phone_number.gsub(/\D/,'')
  raise InvalidPhoneNumberException, "Invalid Phone Number #{phone_number}" if phone_number.length < 4 || phone_number.length > 15
  phone_number
end