harleytt-gvoice-ruby 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.bundle/config +2 -0
- data/.gitignore +5 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +24 -0
- data/README.rdoc +90 -0
- data/Rakefile +12 -0
- data/VERSION +1 -0
- data/bin/gv-notifier +78 -0
- data/bin/gv-place-call +22 -0
- data/bin/gv-send-sms +16 -0
- data/config/gvoice-ruby-config.yml.sample +11 -0
- data/gvoice-ruby.gemspec +34 -0
- data/lib/gvoice-ruby/call.rb +9 -0
- data/lib/gvoice-ruby/client.rb +277 -0
- data/lib/gvoice-ruby/compatibility.rb +75 -0
- data/lib/gvoice-ruby/config.rb +39 -0
- data/lib/gvoice-ruby/errors.rb +5 -0
- data/lib/gvoice-ruby/inbox_parser.rb +126 -0
- data/lib/gvoice-ruby/sms.rb +9 -0
- data/lib/gvoice-ruby/user.rb +12 -0
- data/lib/gvoice-ruby/version.rb +4 -0
- data/lib/gvoice-ruby/voicemail.rb +10 -0
- data/lib/gvoice-ruby.rb +5 -0
- data/test/client_test.rb +59 -0
- data/test/compatibility_test.rb +47 -0
- data/test/config_test.rb +50 -0
- data/test/fixtures/config_fixture.yml +11 -0
- data/test/fixtures/inbox.json +1 -0
- data/test/fixtures/inbox.yml +206 -0
- data/test/fixtures/inbox_fixture.html +2657 -0
- data/test/fixtures/login_fixture.html +567 -0
- data/test/gvoice-ruby_test.rb +9 -0
- data/test/inbox_parser_test.rb +53 -0
- data/test/test_helper.rb +20 -0
- metadata +223 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
# Pathname#ancestor takes an integer argument and walks up the path the same number of steps as the integer argument (starting from zero).
|
5
|
+
# Hence, given the path /Users/foo/bar/baz/bat/quux, Pathname#ancestor(3) would return /Users/foo/bar.
|
6
|
+
Pathname.class_eval do
|
7
|
+
def ancestor(num)
|
8
|
+
temp = self
|
9
|
+
num.downto(1) do
|
10
|
+
temp = temp.parent
|
11
|
+
end
|
12
|
+
return temp
|
13
|
+
end unless method_defined?(:ancestor)
|
14
|
+
end
|
15
|
+
|
16
|
+
if RUBY_VERSION > '1.9'
|
17
|
+
module GvoiceRuby
|
18
|
+
class Call
|
19
|
+
alias_method :orig_display_start_date_time, :display_start_date_time
|
20
|
+
|
21
|
+
def display_start_date_time # New Date class in Ruby 1.9.2 only accepts strictly formatted strings Date.parse
|
22
|
+
if self.send(:caller).first.include?('inbox_parser')
|
23
|
+
orig_display_start_date_time
|
24
|
+
else
|
25
|
+
# Capture the original date string and parse into month, day, year variables
|
26
|
+
# warn "#{self.send(:caller)}"
|
27
|
+
|
28
|
+
orig_display_start_date_time.match(/^(\d)\/(\d{1,2})\/(\d{2})\s(.+)\z/)
|
29
|
+
# month = $1
|
30
|
+
# day = $2
|
31
|
+
year = "20" + $3
|
32
|
+
# warn "Month is: #{month}\nDay is: #{day}\nYear is: #{year}"
|
33
|
+
"#{year}-#{$1}-#{$2} #{$4}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
if RUBY_VERSION < '1.9'
|
41
|
+
|
42
|
+
class Symbol
|
43
|
+
def to_proc
|
44
|
+
proc { |obj, *args| obj.send(self, *args) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Array
|
49
|
+
def sort_by!(&given_proc)
|
50
|
+
if block_given?
|
51
|
+
self.sort! { |a,b| given_proc.call(a) <=> given_proc.call(b) }
|
52
|
+
else
|
53
|
+
raise ArgumentError "No valid proc object created from argument."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
#
|
59
|
+
# class Thing
|
60
|
+
# def initialize
|
61
|
+
# @foo = rand(100)
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# attr_accessor :foo
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# a = []
|
68
|
+
#
|
69
|
+
# 10.times do
|
70
|
+
# a << Thing.new
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# a.sort_by!(&:foo)
|
74
|
+
#
|
75
|
+
# p a
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# $:.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
module GvoiceRuby
|
5
|
+
class Configurator
|
6
|
+
PROJECT_ROOT = File.expand_path(Pathname.new(__FILE__).ancestor(3))
|
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
|
+
# -*- encoding: 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
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module GvoiceRuby
|
3
|
+
class Sms < Struct.new(:id, :start_time, :display_number, :display_start_date_time, :display_start_time, :relative_start_time, :is_read, :starred, :labels, :from, :to, :text)
|
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,12 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module GvoiceRuby
|
3
|
+
class User
|
4
|
+
# User is not a struct because we require email and password attributes
|
5
|
+
attr_accessor :email, :password
|
6
|
+
|
7
|
+
def initialize(email, password)
|
8
|
+
@email = email
|
9
|
+
@password = password
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module GvoiceRuby
|
3
|
+
class Voicemail < Struct.new(:id, :start_time, :display_number, :display_start_date_time, :display_start_time, :relative_start_time, :is_read, :starred, :labels, :from, :to, :transcript, :file)
|
4
|
+
#attr_accessor :id, :start_time, :display_number, :display_start_date_time, :display_start_time, :relative_start_time, :is_read, :labels, :from, :to, :transcript, :file
|
5
|
+
#
|
6
|
+
#def initialize
|
7
|
+
#
|
8
|
+
#end
|
9
|
+
end
|
10
|
+
end
|
data/lib/gvoice-ruby.rb
ADDED
data/test/client_test.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.unshift "." # Ruby 1.9.2 does not include current directory in the path
|
3
|
+
require File.dirname(__FILE__) + "/test_helper"
|
4
|
+
require 'mocha'
|
5
|
+
|
6
|
+
class ClientTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@config_file = File.join(File.dirname(__FILE__), 'fixtures', 'config_fixture.yml')
|
9
|
+
@page_body = String.new(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'login_fixture.html')))
|
10
|
+
end
|
11
|
+
|
12
|
+
should "raise argument error if username nil" do
|
13
|
+
assert_raise(ArgumentError) { GvoiceRuby::Client.new({ :google_account_email => nil }) }
|
14
|
+
end
|
15
|
+
|
16
|
+
should "raise argument error if password nil" do
|
17
|
+
assert_raise(ArgumentError) { GvoiceRuby::Client.new({ :google_account_password => nil }) }
|
18
|
+
end
|
19
|
+
|
20
|
+
should "accept a simple hash as parameters" do
|
21
|
+
Curl::Easy.any_instance.stubs(:perform).returns(true)
|
22
|
+
Curl::Easy.any_instance.stubs(:body_str).returns(@page_body)
|
23
|
+
client = GvoiceRuby::Client.new({:google_account_email => 'google_test_account@gmail.com', :google_account_password => "bar"})
|
24
|
+
assert_kind_of(GvoiceRuby::Client, client)
|
25
|
+
# assert_equal(File.join(File.dirname(File.dirname(__FILE__)), 'log', 'gvoice-ruby.log'),
|
26
|
+
# client.logger.instance_variable_get(:@logdev).instance_variable_get(:@filename))
|
27
|
+
end
|
28
|
+
|
29
|
+
should "raise an error when unable to connect to Google" do
|
30
|
+
# Curl::Easy.any_instance.stubs(:perform).returns(false)
|
31
|
+
# Curl::Easy.any_instance.stubs(:response_code).returns()
|
32
|
+
client = GvoiceRuby::Client.new(GvoiceRuby::Configurator.load_config(@config_file))
|
33
|
+
assert_equal(client.instance_variable_get(:@curb_instance).response_code, 405)
|
34
|
+
end
|
35
|
+
|
36
|
+
should "raise an error when failing to login" do
|
37
|
+
Curl::Easy.any_instance.stubs(:perform).returns(false)
|
38
|
+
assert_raise(GvoiceRuby::LoginFailed) do
|
39
|
+
GvoiceRuby::Client.new({:google_account_email => 'google_test_account@gmail.com', :google_account_password => "bar"})
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
should "login" do
|
44
|
+
Curl::Easy.any_instance.stubs(:body_str).returns(@page_body)
|
45
|
+
client = GvoiceRuby::Client.new(GvoiceRuby::Configurator.load_config(@config_file))
|
46
|
+
assert client.logged_in?
|
47
|
+
assert_kind_of(Curl::Easy, client.instance_variable_get(:@curb_instance))
|
48
|
+
end
|
49
|
+
|
50
|
+
should "logout" do
|
51
|
+
Curl::Easy.any_instance.stubs(:body_str).returns(@page_body)
|
52
|
+
client = GvoiceRuby::Client.new(GvoiceRuby::Configurator.load_config(@config_file))
|
53
|
+
assert client.logged_in?
|
54
|
+
assert_kind_of(Curl::Easy, client.instance_variable_get(:@curb_instance))
|
55
|
+
Curl::Easy.any_instance.stubs(:perform).returns(true)
|
56
|
+
client.logout
|
57
|
+
deny client.logged_in?
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.unshift "." # Ruby 1.9.2 does not include current directory in the path
|
3
|
+
require File.dirname(__FILE__) + "/test_helper"
|
4
|
+
require 'mocha'
|
5
|
+
|
6
|
+
class CompatibilityTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@page_body = String.new(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'inbox_fixture.html')))
|
10
|
+
@inbox_fixture = File.open(File.join(File.dirname(__FILE__), 'fixtures', 'inbox.yml')) { |yf| YAML::load(yf) }
|
11
|
+
@page_obj = mock()
|
12
|
+
@page_obj.stubs(:body_str).returns(@page_body)
|
13
|
+
end
|
14
|
+
|
15
|
+
should "add an instance method to Pathname" do
|
16
|
+
assert Pathname.new("/blah").respond_to?(:ancestor)
|
17
|
+
end
|
18
|
+
|
19
|
+
should "return the appropriate ancestor path" do
|
20
|
+
path = Pathname.new("/Users/foo/bar/baz/bat/quux")
|
21
|
+
assert_equal(Pathname.new("/Users/foo/bar"), path.ancestor(3))
|
22
|
+
end
|
23
|
+
|
24
|
+
if RUBY_VERSION > '1.9'
|
25
|
+
context "Using Ruby 1.9" do
|
26
|
+
should "Provide correct format of the display_start_date_time method" do
|
27
|
+
GvoiceRuby::Client.any_instance.stubs(:fetch_page).returns(true)
|
28
|
+
parser = GvoiceRuby::InboxParser.new
|
29
|
+
inbox = parser.parse_page(@page_obj)
|
30
|
+
parser.parse_calls(inbox['messages'])
|
31
|
+
assert_equal(parser.instance_variable_get(:@calls)[0].display_start_date_time, "2010-2-17 11:36 AM")
|
32
|
+
assert_not_equal(parser.instance_variable_get(:@calls)[0].display_start_date_time, "2/17/2010 11:36 AM")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
context "Using Ruby 1.8" do
|
37
|
+
should "Provide correct format of the display_start_date_time method" do
|
38
|
+
GvoiceRuby::Client.any_instance.stubs(:fetch_page).returns(true)
|
39
|
+
parser = GvoiceRuby::InboxParser.new
|
40
|
+
inbox = parser.parse_page(@page_obj)
|
41
|
+
parser.parse_calls(inbox['messages'])
|
42
|
+
assert_not_equal(parser.instance_variable_get(:@calls)[0].display_start_date_time, "2010-2-17 11:36 AM")
|
43
|
+
assert_equal(parser.instance_variable_get(:@calls)[0].display_start_date_time, "2/17/10 11:36 AM")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/test/config_test.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.dirname(__FILE__) + "/test_helper"
|
3
|
+
|
4
|
+
class ConfigTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@config_file = File.join(File.dirname(__FILE__), 'fixtures', 'config_fixture.yml')
|
8
|
+
@config = GvoiceRuby::Configurator.load_config(@config_file)
|
9
|
+
end
|
10
|
+
|
11
|
+
should "have project root constant" do
|
12
|
+
assert_equal(File.expand_path(File.dirname(__FILE__) + '/..'), GvoiceRuby::Configurator.const_get(:PROJECT_ROOT).to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
should "load configuration file correctly" do
|
16
|
+
@config.each_pair do |k,v|
|
17
|
+
assert_equal(v, @config[k.to_sym])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
should "write configuration file" do
|
22
|
+
@config[:foo] = 'bar'
|
23
|
+
GvoiceRuby::Configurator.write_config(@config, File.dirname(__FILE__) + '/fixtures/config_fixture.yml')
|
24
|
+
newly_loaded_config = GvoiceRuby::Configurator.load_config(File.dirname(__FILE__) + '/fixtures/config_fixture.yml')
|
25
|
+
assert_equal('bar', newly_loaded_config[:foo].to_s)
|
26
|
+
@config.delete(:foo)
|
27
|
+
GvoiceRuby::Configurator.write_config(@config, File.dirname(__FILE__) + '/fixtures/config_fixture.yml')
|
28
|
+
end
|
29
|
+
|
30
|
+
should "raise IOError when config file not loaded" do
|
31
|
+
begin
|
32
|
+
assert_raise(IOError) { GvoiceRuby::Configurator.load_config('foo') }
|
33
|
+
rescue StandardError
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
should "raise IOError when config file not written" do
|
38
|
+
begin
|
39
|
+
assert_raise(IOError) { GvoiceRuby::Configurator.write_config(@config, 'foo') }
|
40
|
+
rescue StandardError
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
should "Load a logger" do
|
45
|
+
assert_equal(@config[:logfile], './log/test_log.log')
|
46
|
+
assert_not_nil(GvoiceRuby::Client.new(@config).logger)
|
47
|
+
assert_not_nil(File.read('./log/test_log.log'))
|
48
|
+
assert_match(/^# Log/, File.read('./log/test_log.log'))
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
---
|
2
|
+
:bot_password: foo
|
3
|
+
:google_service: grandcentral
|
4
|
+
:last_message_start_time: 1252936650000
|
5
|
+
:google_voice_feed_url: https://www.google.com/voice/inbox/recent
|
6
|
+
:google_account_email: google_test_account@gmail.com
|
7
|
+
:bot_name: test_case@jabber.org
|
8
|
+
:google_account_password: bar
|
9
|
+
:logfile: ./log/test_log.log
|
10
|
+
:continue_url: https://www.google.com/voice
|
11
|
+
:google_auth_url: https://www.google.com/accounts/ServiceLoginAuth
|
@@ -0,0 +1 @@
|
|
1
|
+
"{\"messages\":{\"9f051f4869a4aab44b00962187680eb558408343\":{\"id\":\"9f051f4869a4aab44b00962187680eb558408343\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252546280464\",\"displayStartDateTime\":\"9/9/09 8:31 PM\",\"displayStartTime\":\"8:31 PM\",\"relativeStartTime\":\"40 hours ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"sms\",\"all\"],\"type\":10,\"children\":\"\"},\"1c09172ec9043a80b5fe30b6310d84faa8aa1b12\":{\"id\":\"1c09172ec9043a80b5fe30b6310d84faa8aa1b12\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252525590500\",\"displayStartDateTime\":\"9/9/09 2:46 PM\",\"displayStartTime\":\"2:46 PM\",\"relativeStartTime\":\"46 hours ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"sms\",\"all\"],\"type\":10,\"children\":\"\"},\"0cc0fa9a10c91187a182c76a10519185747a05be\":{\"id\":\"0cc0fa9a10c91187a182c76a10519185747a05be\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252517413901\",\"displayStartDateTime\":\"9/9/09 12:30 PM\",\"displayStartTime\":\"12:30 PM\",\"relativeStartTime\":\"2 days ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"sms\",\"all\"],\"type\":10,\"children\":\"\"},\"d8a7642677249d3b35fb029fd806730fe77fa309\":{\"id\":\"d8a7642677249d3b35fb029fd806730fe77fa309\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252449746310\",\"displayStartDateTime\":\"9/8/09 5:42 PM\",\"displayStartTime\":\"5:42 PM\",\"relativeStartTime\":\"2 days ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"sms\",\"all\"],\"type\":10,\"children\":\"\"},\"5ccf9f66a6c3ae9fe05b716d8811a14d2c505a2f\":{\"id\":\"5ccf9f66a6c3ae9fe05b716d8811a14d2c505a2f\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252443634536\",\"displayStartDateTime\":\"9/8/09 4:00 PM\",\"displayStartTime\":\"4:00 PM\",\"relativeStartTime\":\"2 days ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"sms\",\"all\"],\"type\":10,\"children\":\"\"},\"8b710ab3b55926fd5171b0e0394350ec4a38b5ac\":{\"id\":\"8b710ab3b55926fd5171b0e0394350ec4a38b5ac\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252374029866\",\"displayStartDateTime\":\"9/7/09 8:40 PM\",\"displayStartTime\":\"8:40 PM\",\"relativeStartTime\":\"3 days ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"sms\",\"all\"],\"type\":10,\"children\":\"\"},\"38fb0f098daa670ec648b2e947f2a6e4dcfc58a6\":{\"id\":\"38fb0f098daa670ec648b2e947f2a6e4dcfc58a6\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252278164000\",\"displayStartDateTime\":\"9/6/09 6:02 PM\",\"displayStartTime\":\"6:02 PM\",\"relativeStartTime\":\"4 days ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"voicemail\",\"all\"],\"type\":2,\"children\":\"\"},\"833332d3f90330a4d929eb698b4240ad1f79780f\":{\"id\":\"833332d3f90330a4d929eb698b4240ad1f79780f\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252265039929\",\"displayStartDateTime\":\"9/6/09 2:23 PM\",\"displayStartTime\":\"2:23 PM\",\"relativeStartTime\":\"4 days ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"sms\",\"all\"],\"type\":11,\"children\":\"\"},\"79d84552fecdba8160669e479d7897d368a1efb2\":{\"id\":\"79d84552fecdba8160669e479d7897d368a1efb2\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252210001428\",\"displayStartDateTime\":\"9/5/09 11:06 PM\",\"displayStartTime\":\"11:06 PM\",\"relativeStartTime\":\"5 days ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"sms\",\"all\"],\"type\":10,\"children\":\"\"},\"23459dc9b09799115ff5b4c2f0c502a99e934025\":{\"id\":\"23459dc9b09799115ff5b4c2f0c502a99e934025\",\"phoneNumber\":\"+15555555555\",\"displayNumber\":\"(555) 555-5555\",\"startTime\":\"1252180801154\",\"displayStartDateTime\":\"9/5/09 3:00 PM\",\"displayStartTime\":\"3:00 PM\",\"relativeStartTime\":\"5 days ago\",\"note\":\"\",\"isRead\":true,\"isSpam\":false,\"isTrash\":false,\"star\":false,\"labels\":[\"inbox\",\"sms\",\"all\"],\"type\":10,\"children\":\"\"}},\"totalSize\":47,\"unreadCounts\":{\"all\":0,\"inbox\":0,\"missed\":0,\"placed\":0,\"received\":0,\"recorded\":0,\"sms\":0,\"trash\":0,\"unread\":0,\"voicemail\":0},\"resultsPerPage\":10}"
|