roflbot 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitmodules +3 -0
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/roflbot.rb +1 -0
- data/lib/roflbot/base.rb +42 -25
- data/roflbot.gemspec +31 -3
- data/test/helper.rb +10 -0
- data/test/roflbot/test_base.rb +24 -0
- data/vendor/gvoice-ruby/Gemfile +11 -0
- data/vendor/gvoice-ruby/README.rdoc +71 -0
- data/vendor/gvoice-ruby/Rakefile +12 -0
- data/vendor/gvoice-ruby/VERSION +1 -0
- data/vendor/gvoice-ruby/bin/gv-notifier +75 -0
- data/vendor/gvoice-ruby/bin/gv-place-call +18 -0
- data/vendor/gvoice-ruby/bin/gv-send-sms +12 -0
- data/vendor/gvoice-ruby/config/gvoice-ruby-config.yml.sample +10 -0
- data/vendor/gvoice-ruby/lib/gvoice-ruby.rb +6 -0
- data/vendor/gvoice-ruby/lib/gvoice-ruby/call.rb +9 -0
- data/vendor/gvoice-ruby/lib/gvoice-ruby/client.rb +264 -0
- data/vendor/gvoice-ruby/lib/gvoice-ruby/compatibility.rb +37 -0
- data/vendor/gvoice-ruby/lib/gvoice-ruby/config.rb +39 -0
- data/vendor/gvoice-ruby/lib/gvoice-ruby/inbox_parser.rb +126 -0
- data/vendor/gvoice-ruby/lib/gvoice-ruby/sms.rb +9 -0
- data/vendor/gvoice-ruby/lib/gvoice-ruby/user.rb +12 -0
- data/vendor/gvoice-ruby/lib/gvoice-ruby/voicemail.rb +10 -0
- data/vendor/gvoice-ruby/test/client_test.rb +45 -0
- data/vendor/gvoice-ruby/test/config_test.rb +37 -0
- data/vendor/gvoice-ruby/test/fixtures/config_fixture.yml +10 -0
- data/vendor/gvoice-ruby/test/fixtures/inbox.json +1 -0
- data/vendor/gvoice-ruby/test/fixtures/inbox.yml +206 -0
- data/vendor/gvoice-ruby/test/fixtures/inbox_fixture.html +2854 -0
- data/vendor/gvoice-ruby/test/fixtures/login_fixture.html +567 -0
- data/vendor/gvoice-ruby/test/gvoice-ruby_test.rb +9 -0
- data/vendor/gvoice-ruby/test/inbox_parser_test.rb +54 -0
- data/vendor/gvoice-ruby/test/test_helper.rb +19 -0
- metadata +31 -3
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby -W1
|
2
|
+
# coding: UTF-8
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
require 'gvoice-ruby'
|
5
|
+
include GvoiceRuby
|
6
|
+
|
7
|
+
voicebox = GvoiceRuby::Client.new
|
8
|
+
|
9
|
+
txt = {:phone_number => "3088721257", :text => "Testing sms from gvoice-ruby!" }
|
10
|
+
|
11
|
+
puts "Message sent!" if voicebox.send_sms(txt)
|
12
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
---
|
2
|
+
:google_auth_url: https://www.google.com/accounts/ServiceLoginAuth
|
3
|
+
:google_account_password: your_google_account_password
|
4
|
+
:continue_url: https://www.google.com/voice
|
5
|
+
:last_message_start_time: 0
|
6
|
+
:bot_name: your_gtalk_or_jabber_bot_name
|
7
|
+
:google_service: grandcentral
|
8
|
+
:bot_password: your_gtalk_bot_password
|
9
|
+
:google_voice_feed_url: https://www.google.com/voice/inbox/recent
|
10
|
+
:google_account_email: your_google_email_address@gmail.com
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module GvoiceRuby
|
3
|
+
class Call < Struct.new(:id, :start_time, :display_number, :display_start_date_time, :display_start_time, :relative_start_time, :is_read, :starred, :labels, :from, :to)
|
4
|
+
#attr_accessor :id, :start_time, :display_number, :display_start_date_time, :display_start_time, :relative_start_time, :is_read, :labels, :from, :to, :text
|
5
|
+
#
|
6
|
+
#def initialize
|
7
|
+
#end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,264 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
%w[curb nokogiri json sms voicemail call user logger compatibility inbox_parser open-uri].each { |lib| require lib }
|
4
|
+
|
5
|
+
module GvoiceRuby
|
6
|
+
class Client
|
7
|
+
include Curl
|
8
|
+
|
9
|
+
attr_accessor :unread_counts, :smss, :voicemails, :user, :all_messages, :calls
|
10
|
+
attr_reader :logger
|
11
|
+
|
12
|
+
def initialize(config = GvoiceRuby::Configurator.load_config)
|
13
|
+
if config[:google_account_email].nil? || config[:google_account_password].nil?
|
14
|
+
raise ArgumentError, "Invalid Google Account username or password provided."
|
15
|
+
else
|
16
|
+
@logger = Logger.new(config.has_key?(:logfile) ? config[:logfile] : STDERR)
|
17
|
+
@user = User.new(config[:google_account_email], config[:google_account_password])
|
18
|
+
@any_unread = []
|
19
|
+
@unread_counts = {}
|
20
|
+
@all_messages = []
|
21
|
+
initialize_curb
|
22
|
+
end
|
23
|
+
|
24
|
+
login(config)
|
25
|
+
set_rnr_se_token
|
26
|
+
end
|
27
|
+
|
28
|
+
def any_unread?
|
29
|
+
@any_unread
|
30
|
+
end
|
31
|
+
|
32
|
+
def logged_in?
|
33
|
+
!@curb_instance.nil?
|
34
|
+
end
|
35
|
+
|
36
|
+
def check(parser = GvoiceRuby::InboxParser.new)
|
37
|
+
inbox = parser.parse_page(fetch_page)
|
38
|
+
|
39
|
+
get_unread_counts(inbox)
|
40
|
+
@smss = parser.parse_sms_messages(inbox['messages'])
|
41
|
+
@voicemails = parser.parse_voicemail_messages(inbox['messages'])
|
42
|
+
@all_messages = smss | voicemails
|
43
|
+
@all_messages.sort_by!(&:start_time)
|
44
|
+
end
|
45
|
+
|
46
|
+
def missed(parser = GvoiceRuby::InboxParser.new)
|
47
|
+
inbox = parser.parse_page(fetch_page('https://www.google.com/voice/inbox/recent/missed/'))
|
48
|
+
parser.parse_calls(inbox['messages'])
|
49
|
+
end
|
50
|
+
|
51
|
+
def received(parser = GvoiceRuby::InboxParser.new)
|
52
|
+
inbox = parser.parse_page(fetch_page('https://www.google.com/voice/inbox/recent/received/'))
|
53
|
+
parser.parse_calls(inbox['messages'])
|
54
|
+
end
|
55
|
+
|
56
|
+
def placed(parser = GvoiceRuby::InboxParser.new)
|
57
|
+
inbox = parser.parse_page(fetch_page('https://www.google.com/voice/inbox/recent/placed/'))
|
58
|
+
parser.parse_calls(inbox['messages'])
|
59
|
+
end
|
60
|
+
|
61
|
+
def send_sms(options)
|
62
|
+
fields = [ PostField.content('phoneNumber', options[:phone_number]),
|
63
|
+
PostField.content('text', options[:text]),
|
64
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
65
|
+
|
66
|
+
options.merge!({ :post_url => "https://www.google.com/voice/sms/send" })
|
67
|
+
|
68
|
+
post(options, fields)
|
69
|
+
end
|
70
|
+
|
71
|
+
def call(options)
|
72
|
+
fields = [ PostField.content('outgoingNumber', options[:outgoing_number]),
|
73
|
+
PostField.content('forwardingNumber', options[:forwarding_number]),
|
74
|
+
PostField.content('phoneType', options[:phone_type] || 2),
|
75
|
+
PostField.content('subscriberNumber', 'undefined'),
|
76
|
+
PostField.content('remember', 0),
|
77
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
78
|
+
|
79
|
+
options.merge!({ :post_url => "https://www.google.com/voice/call/connect" })
|
80
|
+
|
81
|
+
post(options, fields)
|
82
|
+
end
|
83
|
+
|
84
|
+
def cancel_call(options = {})
|
85
|
+
fields = [ PostField.content('outgoingNumber', options[:outgoing_number] || 'undefined'),
|
86
|
+
PostField.content('forwardingNumber', options[:forwarding_number] || 'undefined'),
|
87
|
+
PostField.content('cancelType', 'C2C'),
|
88
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
89
|
+
|
90
|
+
options.merge!({ :post_url => "https://www.google.com/voice/call/cancel" })
|
91
|
+
|
92
|
+
post(options, fields)
|
93
|
+
end
|
94
|
+
|
95
|
+
def archive(options)
|
96
|
+
fields = [ PostField.content('messages', options[:id]),
|
97
|
+
PostField.content('archive', 1),
|
98
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
99
|
+
|
100
|
+
options.merge!({ :post_url => 'https://www.google.com/voice/inbox/mark'})
|
101
|
+
|
102
|
+
post(options, fields)
|
103
|
+
end
|
104
|
+
|
105
|
+
def mark_as_read(options)
|
106
|
+
fields = [ PostField.content('messages', options[:id]),
|
107
|
+
PostField.content('read', 1),
|
108
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
109
|
+
|
110
|
+
options.merge!({ :post_url => 'https://www.google.com/voice/inbox/mark'})
|
111
|
+
|
112
|
+
post(options, fields)
|
113
|
+
end
|
114
|
+
|
115
|
+
def mark_as_unread(options)
|
116
|
+
fields = [ PostField.content('messages', options[:id]),
|
117
|
+
PostField.content('read', 0),
|
118
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
119
|
+
|
120
|
+
options.merge!({ :post_url => 'https://www.google.com/voice/inbox/mark'})
|
121
|
+
|
122
|
+
post(options, fields)
|
123
|
+
end
|
124
|
+
|
125
|
+
def star(options)
|
126
|
+
fields = [ PostField.content('messages', options[:id]),
|
127
|
+
PostField.content('star', 1),
|
128
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
129
|
+
|
130
|
+
options.merge!({ :post_url => 'https://www.google.com/voice/inbox/star'})
|
131
|
+
|
132
|
+
post(options, fields)
|
133
|
+
end
|
134
|
+
|
135
|
+
def unstar(options)
|
136
|
+
fields = [ PostField.content('messages', options[:id]),
|
137
|
+
PostField.content('star', 0),
|
138
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
139
|
+
|
140
|
+
options.merge!({ :post_url => 'https://www.google.com/voice/inbox/star'})
|
141
|
+
|
142
|
+
post(options, fields)
|
143
|
+
end
|
144
|
+
|
145
|
+
def add_note(options)
|
146
|
+
fields = [ PostField.content('id', options[:id]),
|
147
|
+
PostField.content('note', options[:note]),
|
148
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
149
|
+
|
150
|
+
options.merge!({ :post_url => 'https://www.google.com/voice/inbox/savenote'})
|
151
|
+
|
152
|
+
post(options, fields)
|
153
|
+
end
|
154
|
+
|
155
|
+
def delete_note(options)
|
156
|
+
fields = [ PostField.content('id', options[:id]),
|
157
|
+
PostField.content('_rnr_se', @_rnr_se) ]
|
158
|
+
|
159
|
+
options.merge!({ :post_url => 'https://www.google.com/voice/inbox/deletenote'})
|
160
|
+
|
161
|
+
post(options, fields)
|
162
|
+
end
|
163
|
+
|
164
|
+
def logout
|
165
|
+
if logged_in?
|
166
|
+
@curb_instance.url = "https://www.google.com/voice/account/signout"
|
167
|
+
@curb_instance.perform
|
168
|
+
logger.info logger.info "FINISHED LOGOUT #{@curb_instance.url}: HTTP #{@curb_instance.response_code}"
|
169
|
+
@curb_instance = nil
|
170
|
+
end
|
171
|
+
self
|
172
|
+
end
|
173
|
+
|
174
|
+
private
|
175
|
+
def login(options = {})
|
176
|
+
@curb_instance.url = 'https://www.google.com/accounts/ServiceLoginAuth'
|
177
|
+
@curb_instance.perform
|
178
|
+
|
179
|
+
defeat_google_xsrf(@curb_instance.body_str)
|
180
|
+
|
181
|
+
fields = [ PostField.content('continue', options[:continue_url]), #'https://www.google.com/voice'
|
182
|
+
PostField.content('GALX', @galx),
|
183
|
+
PostField.content('service', options[:google_service]),
|
184
|
+
PostField.content('Email', options[:google_account_email]),
|
185
|
+
PostField.content('Passwd', options[:google_account_password]) ]
|
186
|
+
|
187
|
+
options.merge!({ :post_url => 'https://www.google.com/accounts/ServiceLoginAuth' })
|
188
|
+
|
189
|
+
post(options, fields)
|
190
|
+
end
|
191
|
+
|
192
|
+
def post(options, fields)
|
193
|
+
@curb_instance.url = options[:post_url] #"https://www.google.com/voice/call/connect || https://www.google.com/voice/sms/send"
|
194
|
+
@curb_instance.http_post(fields)
|
195
|
+
|
196
|
+
logger.info "FINISHED POST TO #{options[:post_url]}: HTTP #{@curb_instance.response_code}"
|
197
|
+
return @curb_instance
|
198
|
+
end
|
199
|
+
|
200
|
+
def fetch_page(url = 'https://www.google.com/voice/inbox/recent')
|
201
|
+
|
202
|
+
@curb_instance.url = url #"https://www.google.com/voice/inbox/recent"
|
203
|
+
|
204
|
+
@curb_instance.http_get
|
205
|
+
|
206
|
+
logger.info "FINISHED FETCHING #{url}: HTTP #{@curb_instance.response_code}"
|
207
|
+
return @curb_instance
|
208
|
+
end
|
209
|
+
|
210
|
+
def get_unread_counts(inbox)
|
211
|
+
@unread_counts = inbox['unreadCounts']
|
212
|
+
@any_unread = inbox['unreadCounts']['unread'].to_i != 0
|
213
|
+
logger.info "No unread messages in your Google Voice inbox." unless @any_unread
|
214
|
+
end
|
215
|
+
|
216
|
+
def defeat_google_xsrf(body_string)
|
217
|
+
# defeat Google's XSRF protection
|
218
|
+
doc = Nokogiri::HTML::DocumentFragment.parse(body_string)
|
219
|
+
doc.css('div.loginBox table#gaia_table input').each do |input|
|
220
|
+
if input.to_s =~ /GALX/
|
221
|
+
@galx = input.to_s.scan(/value\="(.+?)"/).flatten!.pop
|
222
|
+
# p @galx
|
223
|
+
else
|
224
|
+
next
|
225
|
+
# raise IOError, 'Cannot fetch galx attribute from Google.'
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def set_rnr_se_token
|
231
|
+
if @curb_instance.response_code == 200 #&& @curb_instance.respond_to?(:perform) # Vestigial?
|
232
|
+
@curb_instance.url = "http://www.google.com/voice"
|
233
|
+
@curb_instance.perform
|
234
|
+
@_rnr_se = extract_rnr_se(@curb_instance.body_str)
|
235
|
+
else
|
236
|
+
raise IOError, "Curb instance was not properly initialized."
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def extract_rnr_se(body_string)
|
241
|
+
begin
|
242
|
+
/value="(.+)"/.match(Nokogiri::HTML::Document.parse(body_string).css('form#gc-search-form').inner_html)
|
243
|
+
return $1
|
244
|
+
rescue IOError
|
245
|
+
raise IOError, "Problem extracting _rnr_se code from page."
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def initialize_curb
|
250
|
+
@curb_instance = Easy.new do |curl|
|
251
|
+
# Google gets mad if you don't fake this...
|
252
|
+
curl.headers["User-Agent"] = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2"
|
253
|
+
# Let's see what happens under the hood
|
254
|
+
# curl.verbose = true
|
255
|
+
|
256
|
+
# Google will redirect us a bit
|
257
|
+
curl.follow_location = true
|
258
|
+
|
259
|
+
# Google will make sure we retain cookies
|
260
|
+
curl.enable_cookies = true
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
if RUBY_VERSION < '1.9'
|
4
|
+
class Symbol
|
5
|
+
def to_proc
|
6
|
+
proc { |obj, *args| obj.send(self, *args) }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Array
|
11
|
+
def sort_by!(&given_proc)
|
12
|
+
if block_given?
|
13
|
+
self.sort! { |a,b| given_proc.call(a) <=> given_proc.call(b) }
|
14
|
+
else
|
15
|
+
raise ArgumentError "No valid proc object created from argument."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
#
|
21
|
+
# class Thing
|
22
|
+
# def initialize
|
23
|
+
# @foo = rand(100)
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# attr_accessor :foo
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# a = []
|
30
|
+
#
|
31
|
+
# 10.times do
|
32
|
+
# a << Thing.new
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# a.sort_by!(&:foo)
|
36
|
+
#
|
37
|
+
# p a
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
module GvoiceRuby
|
5
|
+
class Configurator
|
6
|
+
PROJECT_ROOT = File.expand_path(File.dirname(__FILE__) + '/../..')
|
7
|
+
|
8
|
+
def self.load_config(config_file = File.join(PROJECT_ROOT, 'config', 'gvoice-ruby-config.yml'))
|
9
|
+
# Load our config
|
10
|
+
begin
|
11
|
+
if File.exists?(config_file)
|
12
|
+
config_hash = File.open(config_file) { |yf| YAML::load(yf) }
|
13
|
+
else
|
14
|
+
raise IOError
|
15
|
+
end
|
16
|
+
rescue IOError
|
17
|
+
STDERR.puts "Failed to open file #{File.expand_path(config_file)} for reading. File doesn't seem to exist. (#{$!})"
|
18
|
+
raise
|
19
|
+
end
|
20
|
+
return config_hash
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.write_config(config_hash, config_file = File.join(PROJECT_ROOT, 'config', 'gvoice-ruby-config.yml'))
|
24
|
+
# Clean things up and put them away
|
25
|
+
begin
|
26
|
+
if File.exists?(config_file)
|
27
|
+
File.open(config_file, 'w' ) do |out_file|
|
28
|
+
YAML.dump(config_hash, out_file)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
raise IOError
|
32
|
+
end
|
33
|
+
rescue IOError
|
34
|
+
STDERR.puts "Failed to open #{File.expand_path(config_file)} for writing. File doesn't seem to exist: (#{$!})"
|
35
|
+
raise
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module GvoiceRuby
|
3
|
+
class InboxParser
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@smss = []
|
7
|
+
@voicemails = []
|
8
|
+
@calls = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse_page(page_obj)
|
12
|
+
doc = Nokogiri::XML.parse(page_obj.body_str)
|
13
|
+
|
14
|
+
# p doc
|
15
|
+
|
16
|
+
@html_fragment = Nokogiri::HTML::DocumentFragment.parse(doc.to_html)
|
17
|
+
|
18
|
+
# p @html_fragment
|
19
|
+
|
20
|
+
m = doc.css('json').first.to_s.scan(/CDATA\[(.+)\]\]/).flatten
|
21
|
+
|
22
|
+
inbox = JSON.parse(m.first)
|
23
|
+
return inbox
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_sms_messages(messages, page_fragment = @html_fragment)
|
27
|
+
messages.each do |txt|
|
28
|
+
if txt[1]['type'].to_i == 2
|
29
|
+
next
|
30
|
+
else
|
31
|
+
txt_obj = Sms.new
|
32
|
+
txt_obj.id = txt[0]
|
33
|
+
txt_obj.start_time = txt[1]['startTime'].to_i
|
34
|
+
txt_obj.is_read = txt[1]['isRead']
|
35
|
+
txt_obj.display_start_time = txt[1]['displayStartTime']
|
36
|
+
txt_obj.relative_start_time = txt[1]['relativeStartTime']
|
37
|
+
txt_obj.display_number = txt[1]['displayNumber']
|
38
|
+
txt_obj.display_start_date_time = txt[1]['displayStartDateTime']
|
39
|
+
txt_obj.labels = txt[1]['labels']
|
40
|
+
@smss << txt_obj
|
41
|
+
@smss.sort_by!(&:start_time) #if @smss.respond_to?(:sort_by!)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
@smss.each do |txt_obj|
|
46
|
+
page_fragment.css("div.gc-message-sms-row").each do |row|
|
47
|
+
if row.css('span.gc-message-sms-from').inner_html.strip! =~ /Me:/
|
48
|
+
next
|
49
|
+
elsif row.css('span.gc-message-sms-time').inner_html =~ Regexp.new(txt_obj.display_start_time)
|
50
|
+
txt_obj.to = 'Me'
|
51
|
+
txt_obj.from = row.css('span.gc-message-sms-from').inner_html.strip!.gsub!(':', '')
|
52
|
+
txt_obj.text = row.css('span.gc-message-sms-text').inner_html
|
53
|
+
# txt_obj.time = row.css('span.gc-message-sms-time').inner_html
|
54
|
+
else
|
55
|
+
next
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_voicemail_messages(messages, page_fragment = @html_fragment)
|
62
|
+
# p messages
|
63
|
+
messages.each do |msg|
|
64
|
+
if msg[1]['type'].to_i == 2
|
65
|
+
vm_obj = Voicemail.new
|
66
|
+
vm_obj.id = msg[0]
|
67
|
+
vm_obj.start_time = msg[1]['startTime'].to_i
|
68
|
+
vm_obj.is_read = msg[1]['isRead']
|
69
|
+
vm_obj.display_start_time = msg[1]['displayStartTime']
|
70
|
+
vm_obj.relative_start_time = msg[1]['relativeStartTime']
|
71
|
+
vm_obj.display_number = msg[1]['displayNumber']
|
72
|
+
vm_obj.display_start_date_time = msg[1]['displayStartDateTime']
|
73
|
+
vm_obj.labels = msg[1]['labels']
|
74
|
+
@voicemails << vm_obj
|
75
|
+
@voicemails.sort_by!(&:start_time)
|
76
|
+
else
|
77
|
+
next
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
@voicemails.each do |vm_obj|
|
82
|
+
page_fragment.css('table.gc-message-tbl').each do |row|
|
83
|
+
if row.css('span.gc-message-time').text =~ Regexp.new(vm_obj.display_start_date_time)
|
84
|
+
vm_obj.to = 'Me'
|
85
|
+
vm_obj.from = row.css('a.gc-under.gc-message-name-link').inner_html
|
86
|
+
vm_obj.transcript = row.css('div.gc-message-message-display').inner_text.to_s.gsub(/\n/, "").squeeze(" ").strip!
|
87
|
+
# vm_obj.time = row.css('span.gc-message-time').inner_html
|
88
|
+
else
|
89
|
+
next
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse_calls(messages, page_fragment = @html_fragment)
|
96
|
+
messages.each do |msg|
|
97
|
+
call_obj = Call.new
|
98
|
+
call_obj.id = msg[0]
|
99
|
+
call_obj.start_time = msg[1]['startTime'].to_i
|
100
|
+
call_obj.is_read = msg[1]['isRead']
|
101
|
+
call_obj.display_start_time = msg[1]['displayStartTime']
|
102
|
+
call_obj.relative_start_time = msg[1]['relativeStartTime']
|
103
|
+
call_obj.display_number = msg[1]['displayNumber']
|
104
|
+
call_obj.display_start_date_time = msg[1]['displayStartDateTime']
|
105
|
+
call_obj.labels = msg[1]['labels']
|
106
|
+
|
107
|
+
@calls << call_obj
|
108
|
+
@calls.sort_by!(&:start_time)
|
109
|
+
end
|
110
|
+
|
111
|
+
@calls.each do |call_obj|
|
112
|
+
page_fragment.css('table.gc-message-tbl').each do |row|
|
113
|
+
if row.css('span.gc-message-time').text =~ Regexp.new(call_obj.display_start_date_time)
|
114
|
+
call_obj.to = 'Me'
|
115
|
+
call_obj.from = call_obj.display_number
|
116
|
+
# call_obj.from = row.css('a.gc-under.gc-message-name-link').inner_html
|
117
|
+
# call_obj.transcript = row.css('div.gc-message-message-display').inner_text.to_s.gsub(/\n/, "").squeeze(" ").strip!
|
118
|
+
# call_obj.time = row.css('span.gc-message-time').inner_html
|
119
|
+
else
|
120
|
+
next
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|