contacts 1.2.3 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -43,13 +43,13 @@ spec = Gem::Specification.new do |s|
43
43
 
44
44
  #### Basic information.
45
45
 
46
- s.name = 'adamhunter-contacts'
46
+ s.name = 'contacts'
47
47
  s.version = PKG_VERSION
48
48
  s.summary = <<-EOF
49
- Ridiculously easy contact list information from various providers including Yahoo, Gmail, and Hotmail
49
+ A universal interface to grab contact list information from various providers including Yahoo, AOL, Gmail, Hotmail, and Plaxo.
50
50
  EOF
51
51
  s.description = <<-EOF
52
- Ridiculously easy contact list information from various providers including Yahoo, Gmail, and Hotmail
52
+ A universal interface to grab contact list information from various providers including Yahoo, AOL, Gmail, Hotmail, and Plaxo.
53
53
  EOF
54
54
 
55
55
  #### Which files are to be included in this gem? Everything! (Except CVS directories.)
@@ -13,7 +13,10 @@ class Contacts
13
13
  PROTOCOL_ERROR = "AOL has changed its protocols, please upgrade this library first. If that does not work, dive into the code and submit a patch at http://github.com/cardmagic/contacts"
14
14
 
15
15
  def real_connect
16
-
16
+ if login.strip =~ /^(.+)@aol\.com$/ # strip off the @aol.com for AOL logins
17
+ login = $1
18
+ end
19
+
17
20
  postdata = {
18
21
  "loginId" => login,
19
22
  "password" => password,
@@ -77,7 +80,7 @@ class Contacts
77
80
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
78
81
  end
79
82
 
80
- if data.index("Invalid Screen Name or Password.")
83
+ if data.index("Invalid Username or Password. Please try again.")
81
84
  raise AuthenticationError, "Username and password do not match"
82
85
  elsif data.index("Required field must not be blank")
83
86
  raise AuthenticationError, "Login and password must not be blank"
@@ -9,7 +9,7 @@ require "erb"
9
9
 
10
10
  class Contacts
11
11
  TYPES = {}
12
- VERSION = "1.2.3"
12
+ VERSION = "1.2.4"
13
13
 
14
14
  class Base
15
15
  def initialize(login, password, options={})
@@ -78,9 +78,9 @@ class Contacts
78
78
  email_match_text_beginning = Regexp.escape("http://m.mail.live.com/?rru=compose&amp;to=")
79
79
  email_match_text_end = Regexp.escape("&amp;")
80
80
 
81
- raw_html = resp.body.grep(/(?:e|dn)lk[0-9]+/)
82
- raw_html.delete_at 0
83
- raw_html.inject do |memo, row|
81
+ raw_html = resp.body.split("
82
+ ").grep(/(?:e|dn)lk[0-9]+/)
83
+ raw_html.inject(-1) do |memo, row|
84
84
  c_info = row.match(/(e|dn)lk([0-9])+/)
85
85
 
86
86
  # Same contact, or different?
@@ -109,6 +109,7 @@ class Contacts
109
109
  @contacts << contact
110
110
  end
111
111
  end
112
+
112
113
  return @contacts
113
114
  end
114
115
  end
@@ -62,15 +62,11 @@ class Contacts
62
62
  raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
63
63
  end
64
64
 
65
- parse data
66
-
67
- parse more_data
68
-
69
65
  if more_data =~ /"TotalABContacts":(\d+)/
70
66
  total = $1.to_i
71
- ((total / 50)).times do |i|
67
+ ((total / 50.0).ceil).times do |i|
72
68
  # now proceed with the new ".crumb" parameter to get the csv data
73
- url = URI.parse(contact_list_url.sub("bucket=1","bucket=#{i+2}").sub("_crumb=crumb","_crumb=#{crumb}").sub("time", Time.now.to_f.to_s.sub(".","")[0...-2]))
69
+ url = URI.parse(contact_list_url.sub("bucket=1","bucket=#{i}").sub("_crumb=crumb","_crumb=#{crumb}").sub("time", Time.now.to_f.to_s.sub(".","")[0...-2]))
74
70
  http = open_http(url)
75
71
  resp, more_data = http.get("#{url.path}?#{url.query}",
76
72
  "Cookie" => @cookies,
@@ -81,7 +77,7 @@ class Contacts
81
77
  if resp.code_type != Net::HTTPOK
82
78
  raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
83
79
  end
84
-
80
+
85
81
  parse more_data
86
82
  end
87
83
  end
@@ -94,13 +90,11 @@ class Contacts
94
90
 
95
91
  def parse(data, options={})
96
92
  @contacts ||= []
97
- if data =~ /var InitialContacts = (\[.*?\]);/
98
- @contacts += Contacts.parse_json($1).select{|contact|!contact["email"].to_s.empty?}.map{|contact|[contact["contactName"], contact["email"]]}
99
- elsif data =~ /^\{"response":/
100
- @contacts += Contacts.parse_json(data)["response"]["ResultSet"]["Contacts"].to_a.select{|contact|!contact["email"].to_s.empty?}.map{|contact|[contact["contactName"], contact["email"]]}
101
- else
102
- @contacts
103
- end
93
+ @contacts += Contacts.parse_json(data)["response"]["ResultSet"]["Contacts"].to_a.select{|contact|!contact["email"].to_s.empty?}.map do |contact|
94
+ name = contact["contactName"].split(",")
95
+ [[name.pop, name.join(",")].join(" ").strip, contact["email"]]
96
+ end if data =~ /^\{"response":/
97
+ @contacts
104
98
  end
105
99
 
106
100
  end
@@ -0,0 +1,40 @@
1
+ gmail:
2
+ username: <changeme>
3
+ password: <changeme>
4
+ contacts:
5
+ -
6
+ name: "FirstName1 LastName1"
7
+ email_address: "firstname1@example.com"
8
+ -
9
+ name: "FirstName2 LastName2"
10
+ email_address: "firstname2@example.com"
11
+ yahoo:
12
+ username: <changeme>
13
+ password: <changeme>
14
+ contacts:
15
+ -
16
+ name: "FirstName1 LastName1"
17
+ email_address: "firstname1@example.com"
18
+ -
19
+ name: "FirstName2 LastName2"
20
+ email_address: "firstname2@example.com"
21
+ hotmail:
22
+ username: <changeme>
23
+ password: <changeme>
24
+ contacts:
25
+ -
26
+ name: "FirstName1 LastName1"
27
+ email_address: "firstname1@example.com"
28
+ -
29
+ name: "FirstName2 LastName2"
30
+ email_address: "firstname2@example.com"
31
+ aol:
32
+ username: <changeme>
33
+ password: <changeme>
34
+ contacts:
35
+ -
36
+ name: "FirstName1 LastName1"
37
+ email_address: "firstname1@example.com"
38
+ -
39
+ name: "FirstName2 LastName2"
40
+ email_address: "firstname2@example.com"
@@ -0,0 +1,31 @@
1
+ dir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(dir + "/../lib/")
3
+ require 'test/unit'
4
+ require 'contacts'
5
+ require 'yaml'
6
+
7
+ class ContactImporterTestCase < Test::Unit::TestCase
8
+ # Add more helper methods to be used by all tests here...
9
+ def default_test
10
+ assert true
11
+ end
12
+ end
13
+
14
+ class TestAccounts
15
+ def self.[](type)
16
+ load[type]
17
+ end
18
+
19
+ def self.load(file = File.dirname(__FILE__) + "/accounts.yml")
20
+ raise "/test/accounts.yml file not found, please create, see /test/example_accounts.yml for information" unless File.exist?(file)
21
+
22
+ accounts = {}
23
+ YAML::load(File.open(file)).each do |type, contents|
24
+ contacts = contents["contacts"].collect {|contact| [contact["name"], contact["email_address"]]}
25
+ accounts[type.to_sym] = Account.new(type.to_sym, contents["username"], contents["password"], contacts)
26
+ end
27
+ accounts
28
+ end
29
+
30
+ Account = Struct.new :type, :username, :password, :contacts
31
+ end
@@ -0,0 +1,4 @@
1
+ dir = File.dirname(__FILE__)
2
+ Dir["#{dir}/**/*_test.rb"].each do |file|
3
+ require file
4
+ end
@@ -0,0 +1,39 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/../test_helper"
3
+ require 'contacts'
4
+
5
+ class AolContactImporterTest < ContactImporterTestCase
6
+ def setup
7
+ super
8
+ @account = TestAccounts[:aol]
9
+ end
10
+
11
+ def test_successful_login
12
+ Contacts.new(:aol, @account.username, @account.password)
13
+ end
14
+
15
+ def test_importer_fails_with_invalid_password
16
+ assert_raise(Contacts::AuthenticationError) do
17
+ Contacts.new(:aol, @account.username, "wrong_password")
18
+ end
19
+ end
20
+
21
+ def test_importer_fails_with_blank_password
22
+ assert_raise(Contacts::AuthenticationError) do
23
+ Contacts.new(:aol, @account.username, "")
24
+ end
25
+ end
26
+
27
+ def test_importer_fails_with_blank_username
28
+ assert_raise(Contacts::AuthenticationError) do
29
+ Contacts.new(:aol, "", @account.password)
30
+ end
31
+ end
32
+
33
+ def test_fetch_contacts
34
+ contacts = Contacts.new(:aol, @account.username, @account.password).contacts
35
+ @account.contacts.each do |contact|
36
+ assert contacts.include?(contact), "Could not find: #{contact.inspect} in #{contacts.inspect}"
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/../test_helper"
3
+ require 'contacts'
4
+
5
+ class GmailContactImporterTest < ContactImporterTestCase
6
+ def setup
7
+ super
8
+ @account = TestAccounts[:gmail]
9
+ end
10
+
11
+ def test_successful_login
12
+ Contacts.new(:gmail, @account.username, @account.password)
13
+ end
14
+
15
+ def test_importer_fails_with_invalid_password
16
+ assert_raise(Contacts::AuthenticationError) do
17
+ Contacts.new(:gmail, @account.username, "wrong_password")
18
+ end
19
+ end
20
+
21
+ def test_importer_fails_with_blank_password
22
+ assert_raise(Contacts::AuthenticationError) do
23
+ Contacts.new(:gmail, @account.username, "")
24
+ end
25
+ end
26
+
27
+ def test_importer_fails_with_blank_username
28
+ assert_raise(Contacts::AuthenticationError) do
29
+ Contacts.new(:gmail, "", @account.password)
30
+ end
31
+ end
32
+
33
+ def test_fetch_contacts
34
+ contacts = Contacts.new(:gmail, @account.username, @account.password).contacts
35
+ @account.contacts.each do |contact|
36
+ assert contacts.include?(contact), "Could not find: #{contact.inspect} in #{contacts.inspect}"
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,41 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/../test_helper"
3
+ require 'contacts'
4
+
5
+ class HotmailContactImporterTest < ContactImporterTestCase
6
+ def setup
7
+ super
8
+ @account = TestAccounts[:hotmail]
9
+ end
10
+
11
+ def test_successful_login
12
+ Contacts.new(:hotmail, @account.username, @account.password)
13
+ end
14
+
15
+ def test_importer_fails_with_invalid_password
16
+ assert_raise(Contacts::AuthenticationError) do
17
+ Contacts.new(:hotmail, @account.username,"wrong_password")
18
+ end
19
+ end
20
+
21
+ def test_fetch_contacts
22
+ contacts = Contacts.new(:hotmail, @account.username, @account.password).contacts
23
+ @account.contacts.each do |contact|
24
+ assert contacts.include?(contact), "Could not find: #{contact.inspect} in #{contacts.inspect}"
25
+ end
26
+ end
27
+
28
+ def test_importer_fails_with_invalid_msn_password
29
+ assert_raise(Contacts::AuthenticationError) do
30
+ Contacts.new(:hotmail, "test@msn.com","wrong_password")
31
+ end
32
+ end
33
+
34
+ # Since the hotmail scraper doesn't read names, test email
35
+ def test_fetch_email
36
+ contacts = Contacts.new(:hotmail, @account.username, @account.password).contacts
37
+ @account.contacts.each do |contact|
38
+ assert contacts.any?{|book_contact| book_contact.last == contact.last }, "Could not find: #{contact.inspect} in #{contacts.inspect}"
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/../test_helper"
3
+
4
+ class TestAccountsTest < ContactImporterTestCase
5
+ def test_test_accounts_loads_data_from_example_accounts_file
6
+ account = TestAccounts.load(File.dirname(__FILE__) + "/../example_accounts.yml")[:gmail]
7
+
8
+ assert_equal :gmail, account.type
9
+ assert_equal "<changeme>", account.username
10
+ assert_equal "<changeme>", account.password
11
+ assert_equal [["FirstName1 LastName1", "firstname1@example.com"], ["FirstName2 LastName2", "firstname2@example.com"]], account.contacts
12
+ end
13
+
14
+ def test_test_accounts_blows_up_if_file_doesnt_exist
15
+ assert_raise(RuntimeError) do
16
+ TestAccounts.load("file_that_does_not_exist.yml")
17
+ end
18
+ end
19
+
20
+ def test_we_can_load_from_account_file
21
+ assert_not_nil TestAccounts[:gmail].username
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/../test_helper"
3
+ require 'contacts'
4
+
5
+ class YahooContactImporterTest < ContactImporterTestCase
6
+ def setup
7
+ super
8
+ @account = TestAccounts[:yahoo]
9
+ end
10
+
11
+ def test_a_successful_login
12
+ Contacts.new(:yahoo, @account.username, @account.password)
13
+ end
14
+
15
+ def test_importer_fails_with_invalid_password
16
+ assert_raise(Contacts::AuthenticationError) do
17
+ Contacts.new(:yahoo, @account.username, "wrong_password")
18
+ end
19
+ # run the "successful" login test to ensure we reset yahoo's failed login lockout counter
20
+ # See http://www.pivotaltracker.com/story/show/138210
21
+ # yahoo needs some time to unset the failed login state, apparently...
22
+ # ...1 sec and 5 secs still failed sporadically
23
+ sleep 10
24
+ assert_nothing_raised do
25
+ Contacts.new(:yahoo, @account.username, @account.password)
26
+ end
27
+ end
28
+
29
+ def test_a_fetch_contacts
30
+ contacts = Contacts.new(:yahoo, @account.username, @account.password).contacts
31
+ @account.contacts.each do |contact|
32
+ assert contacts.include?(contact), "Could not find: #{contact.inspect} in #{contacts.inspect}"
33
+ end
34
+ end
35
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contacts
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.3
4
+ version: 1.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Carlson
8
- autorequire:
8
+ autorequire: contacts
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-20 00:00:00 -08:00
12
+ date: 2010-07-06 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 1.1.1
23
+ version: 0.4.1
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: gdata
@@ -28,11 +28,11 @@ dependencies:
28
28
  version_requirement:
29
29
  version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.1.1
34
34
  version:
35
- description: A universal interface to grab contact list information from various providers including Yahoo, AOL, Gmail, Hotmail, and Plaxo.
35
+ description: " A universal interface to grab contact list information from various providers including Yahoo, AOL, Gmail, Hotmail, and Plaxo.\n"
36
36
  email: lucas@rufy.com
37
37
  executables: []
38
38
 
@@ -41,20 +41,28 @@ extensions: []
41
41
  extra_rdoc_files: []
42
42
 
43
43
  files:
44
- - LICENSE
45
- - Rakefile
46
- - README
47
- - examples/grab_contacts.rb
48
- - lib/contacts.rb
44
+ - lib/contacts/aol.rb
49
45
  - lib/contacts/base.rb
50
- - lib/contacts/json_picker.rb
51
46
  - lib/contacts/gmail.rb
52
- - lib/contacts/aol.rb
53
47
  - lib/contacts/hotmail.rb
48
+ - lib/contacts/json_picker.rb
54
49
  - lib/contacts/plaxo.rb
55
50
  - lib/contacts/yahoo.rb
51
+ - lib/contacts.rb
52
+ - test/example_accounts.yml
53
+ - test/test_helper.rb
54
+ - test/test_suite.rb
55
+ - test/unit/aol_contact_importer_test.rb
56
+ - test/unit/gmail_contact_importer_test.rb
57
+ - test/unit/hotmail_contact_importer_test.rb
58
+ - test/unit/test_accounts_test.rb
59
+ - test/unit/yahoo_csv_contact_importer_test.rb
60
+ - LICENSE
61
+ - Rakefile
62
+ - README
63
+ - examples/grab_contacts.rb
56
64
  has_rdoc: true
57
- homepage: http://github.com/cardmagic/contacts
65
+ homepage: http://rubyforge.org/projects/contacts
58
66
  licenses: []
59
67
 
60
68
  post_install_message:
@@ -74,8 +82,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
82
  - !ruby/object:Gem::Version
75
83
  version: "0"
76
84
  version:
77
- requirements: []
78
-
85
+ requirements:
86
+ - A json parser, the gdata ruby gem
79
87
  rubyforge_project:
80
88
  rubygems_version: 1.3.5
81
89
  signing_key: