toferboy-contacts 1.2.3 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,57 +1,7 @@
1
- == Welcome to Contacts
1
+ === Slimmed-down version of Contacts
2
2
 
3
- Contacts is a universal interface to grab contact list information from various providers including Hotmail, AOL, Gmail, Plaxo and Yahoo.
4
-
5
- == Download
6
-
7
- * gem install contacts
8
- * http://github.com/cardmagic/contacts
9
- * git clone git://github.com/cardmagic/contacts.git
10
-
11
- == Background
12
-
13
- For a long time, the only way to get a list of contacts from your free online email accounts was with proprietary PHP scripts that would cost you $50. The act of grabbing that list is a simple matter of screen scrapping and this library gives you all the functionality you need. Thanks to the generosity of the highly popular Rails website MOG (http://mog.com) for allowing this library to be released open-source to the world. It is easy to extend this library to add new free email providers, so please contact the author if you would like to help.
14
-
15
- == Usage
16
-
17
- Contacts::Hotmail.new(login, password).contacts # => [["name", "foo@bar.com"], ["another name", "bow@wow.com"]]
18
- Contacts::Yahoo.new(login, password).contacts
19
- Contacts::Gmail.new(login, password).contacts
20
-
21
- Contacts.new(:gmail, login, password).contacts
22
- Contacts.new(:hotmail, login, password).contacts
23
- Contacts.new(:yahoo, login, password).contacts
24
-
25
- Contacts.guess(login, password).contacts
26
-
27
- Notice there are three ways to use this library so that you can limit the use as much as you would like in your particular application. The Contacts.guess method will automatically concatenate all the address book contacts from each of the successful logins in the case that a username password works across multiple services.
28
-
29
- == Captcha error
30
-
31
- If there are too many failed attempts with the gmail login info, Google will raise a captcha response. To integrate the captcha handling, pass in the token and response via:
32
-
33
- Contacts::Gmail.new(login, password, :captcha_token => params[:captcha_token], :captcha_response => params[:captcha_response]).contacts
34
-
35
- == Examples
36
-
37
- See the examples/ directory.
38
-
39
- == Authors
40
-
41
- * Lucas Carlson from MOG (mailto:lucas@rufy.com) - http://mog.com
42
-
43
- == Contributors
44
-
45
- * Britt Selvitelle from Twitter (mailto:anotherbritt@gmail.com) - http://twitter.com
46
- * Tony Targonski from GigPark (mailto:tony@gigpark.com) - http://gigpark.com
47
- * Waheed Barghouthi from Watwet (mailto:waheed.barghouthi@gmail.com) - http://watwet.com
48
- * Glenn Sidney from Glenn Fu (mailto:glenn@glennfu.com) - http://glennfu.com
49
- * Brian McQuay from Onomojo (mailto:brian@onomojo.com) - http://onomojo.com
50
- * Adam Hunter (mailto:adamhunter@me.com) - http://adamhunter.me/
51
- * Glenn Ford (mailto:glenn@glennfu.com) - http://www.glennfu.com/
52
- * Leonardo Wong (mailto:mac@boy.name)
53
- * Rusty Burchfield
54
- * justintv
55
-
56
- This library is released under the terms of the BSD.
3
+ Andreas: Install this gem by cloning down the source, and then running
4
+ gem build GEMNAME.gemspec
5
+ gem install gemname-version.gem
57
6
 
7
+ Contacts::Gmail.new(login, password).contacts
data/Rakefile CHANGED
@@ -43,7 +43,7 @@ spec = Gem::Specification.new do |s|
43
43
 
44
44
  #### Basic information.
45
45
 
46
- s.name = 'adamhunter-contacts'
46
+ s.name = 'contacts19'
47
47
  s.version = PKG_VERSION
48
48
  s.summary = <<-EOF
49
49
  Ridiculously easy contact list information from various providers including Yahoo, Gmail, and Hotmail
@@ -88,4 +88,4 @@ task :stats do
88
88
  ["Library", "lib"],
89
89
  ["Units", "test"]
90
90
  ).to_s
91
- end
91
+ end
@@ -1,19 +1,59 @@
1
+ require 'hpricot'
2
+ require 'csv'
3
+
1
4
  class Contacts
2
- require 'hpricot'
3
- require 'csv'
4
- class Aol < Base
5
+ class AolImporter < Base
5
6
  URL = "http://www.aol.com/"
6
7
  LOGIN_URL = "https://my.screenname.aol.com/_cqr/login/login.psp"
7
8
  LOGIN_REFERER_URL = "http://webmail.aol.com/"
8
9
  LOGIN_REFERER_PATH = "sitedomain=sns.webmail.aol.com&lang=en&locale=us&authLev=0&uitype=mini&loginId=&redirType=js&xchk=false"
9
- AOL_NUM = "29970-343" # this seems to change each time they change the protocol
10
-
11
- CONTACT_LIST_URL = "http://webmail.aol.com/#{AOL_NUM}/aim-2/en-us/Lite/ContactList.aspx?folder=Inbox&showUserFolders=False"
12
- CONTACT_LIST_CSV_URL = "http://webmail.aol.com/#{AOL_NUM}/aim-2/en-us/Lite/ABExport.aspx?command=all"
10
+ AOL_NUM = "32319-211" # this seems to change each time they change the protocol
11
+
12
+ CONTACT_LIST_URL = "http://mail.aol.com/#{AOL_NUM}/aol-6/en-us/Lite/ContactList.aspx?folder=Inbox&showUserFolders=False"
13
+ CONTACT_LIST_CSV_URL = "http://mail.aol.com/#{AOL_NUM}/aol-6/en-us/Lite/ABExport.aspx?command=all"
13
14
  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
-
15
+
16
+ def contacts
17
+ postdata = {
18
+ "file" => 'contacts',
19
+ "fileType" => 'csv'
20
+ }
21
+
22
+ return @contacts if @contacts
23
+ if connected?
24
+ data, resp, cookies, forward, old_url = get(CONTACT_LIST_URL, @cookies, CONTACT_LIST_URL) + [CONTACT_LIST_URL]
25
+
26
+ until forward.nil?
27
+ data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
28
+ end
29
+
30
+ if resp.code_type != Net::HTTPOK
31
+ raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
32
+ end
33
+
34
+ # parse data and grab <input name="user" value="8QzMPIAKs2" type="hidden">
35
+ doc = Hpricot(data)
36
+ (doc/:input).each do |input|
37
+ postdata["user"] = input.attributes["value"] if input.attributes["name"] == "user"
38
+ end
39
+
40
+ data, resp, cookies, forward, old_url = get(CONTACT_LIST_CSV_URL, @cookies, CONTACT_LIST_URL) + [CONTACT_LIST_URL]
41
+
42
+ until forward.nil?
43
+ data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
44
+ end
45
+
46
+ if data.include?("error.gif")
47
+ raise AuthenticationError, "Account invalid"
48
+ end
49
+
50
+ parse data
51
+ end
52
+ end
53
+
54
+
15
55
  def real_connect
16
-
56
+
17
57
  postdata = {
18
58
  "loginId" => login,
19
59
  "password" => password,
@@ -44,40 +84,40 @@ class Contacts
44
84
  "redirType" => "",
45
85
  "xchk" => "false"
46
86
  }
47
-
87
+
48
88
  # Get this cookie and stick it in the form to confirm to Aol that your cookies work
49
89
  data, resp, cookies, forward = get(URL)
50
90
  postdata["stips"] = cookie_hash_from_string(cookies)["stips"]
51
91
  postdata["tst"] = cookie_hash_from_string(cookies)["tst"]
52
-
92
+
53
93
  data, resp, cookies, forward, old_url = get(LOGIN_REFERER_URL, cookies) + [URL]
54
94
  until forward.nil?
55
95
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
56
96
  end
57
-
97
+
58
98
  data, resp, cookies, forward, old_url = get("#{LOGIN_URL}?#{LOGIN_REFERER_PATH}", cookies) + [LOGIN_REFERER_URL]
59
99
  until forward.nil?
60
100
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
61
101
  end
62
-
102
+
63
103
  doc = Hpricot(data)
64
104
  (doc/:input).each do |input|
65
105
  postdata["usrd"] = input.attributes["value"] if input.attributes["name"] == "usrd"
66
106
  end
67
107
  # parse data for <input name="usrd" value="2726212" type="hidden"> and add it to the postdata
68
-
108
+
69
109
  postdata["SNS_SC"] = cookie_hash_from_string(cookies)["SNS_SC"]
70
110
  postdata["SNS_LDC"] = cookie_hash_from_string(cookies)["SNS_LDC"]
71
111
  postdata["LTState"] = cookie_hash_from_string(cookies)["LTState"]
72
112
  # raise data.inspect
73
-
113
+
74
114
  data, resp, cookies, forward, old_url = post(LOGIN_URL, h_to_query_string(postdata), cookies, LOGIN_REFERER_URL) + [LOGIN_REFERER_URL]
75
-
115
+
76
116
  until forward.nil?
77
117
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
78
118
  end
79
-
80
- if data.index("Invalid Screen Name or Password.")
119
+
120
+ if data.index("Invalid Password, Username or Email")
81
121
  raise AuthenticationError, "Username and password do not match"
82
122
  elsif data.index("Required field must not be blank")
83
123
  raise AuthenticationError, "Login and password must not be blank"
@@ -88,64 +128,23 @@ class Contacts
88
128
  elsif cookies == ""
89
129
  raise ConnectionError, PROTOCOL_ERROR
90
130
  end
91
-
131
+
92
132
  @cookies = cookies
93
133
  end
94
-
95
- def contacts
96
- postdata = {
97
- "file" => 'contacts',
98
- "fileType" => 'csv'
99
- }
100
-
101
- return @contacts if @contacts
102
- if connected?
103
- data, resp, cookies, forward, old_url = get(CONTACT_LIST_URL, @cookies, CONTACT_LIST_URL) + [CONTACT_LIST_URL]
104
-
105
- until forward.nil?
106
- data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
107
- end
108
-
109
- if resp.code_type != Net::HTTPOK
110
- raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
111
- end
112
-
113
- # parse data and grab <input name="user" value="8QzMPIAKs2" type="hidden">
114
- doc = Hpricot(data)
115
- (doc/:input).each do |input|
116
- postdata["user"] = input.attributes["value"] if input.attributes["name"] == "user"
117
- end
118
-
119
- data, resp, cookies, forward, old_url = get(CONTACT_LIST_CSV_URL, @cookies, CONTACT_LIST_URL) + [CONTACT_LIST_URL]
120
-
121
- until forward.nil?
122
- data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
123
- end
124
-
125
- if data.include?("error.gif")
126
- raise AuthenticationError, "Account invalid"
127
- end
128
-
129
- parse data
130
- end
131
- end
132
- private
133
-
134
+
135
+
134
136
  def parse(data, options={})
135
- data = CSV::Reader.parse(data)
137
+ data = CSV.parse(data)
136
138
  col_names = data.shift
137
139
  @contacts = data.map do |person|
138
140
  ["#{person[0]} #{person[1]}", person[4]] if person[4] && !person[4].empty?
139
141
  end.compact
140
- end
141
-
142
+ end
143
+
142
144
  def h_to_query_string(hash)
143
145
  u = ERB::Util.method(:u)
144
- hash.map { |k, v|
145
- u.call(k) + "=" + u.call(v)
146
- }.join("&")
146
+ hash.map{ |k, v| u.call(k) + "=" + u.call(v) }.join("&")
147
147
  end
148
148
  end
149
-
150
- TYPES[:aol] = Aol
149
+ TYPES[:aolImporter] = AolImporter
151
150
  end
data/lib/contacts/base.rb CHANGED
@@ -9,8 +9,9 @@ require "erb"
9
9
 
10
10
  class Contacts
11
11
  TYPES = {}
12
- VERSION = "1.2.3"
13
-
12
+ FILETYPES = {}
13
+ VERSION = "1.4.1"
14
+
14
15
  class Base
15
16
  def initialize(login, password, options={})
16
17
  @login = login
@@ -20,12 +21,12 @@ class Contacts
20
21
  @connections = {}
21
22
  connect
22
23
  end
23
-
24
+
24
25
  def connect
25
26
  raise AuthenticationError, "Login and password must not be nil, login: #{@login.inspect}, password: #{@password.inspect}" if @login.nil? || @login.empty? || @password.nil? || @password.empty?
26
27
  real_connect
27
28
  end
28
-
29
+
29
30
  def connected?
30
31
  @cookies && !@cookies.empty?
31
32
  end
@@ -38,19 +39,19 @@ class Contacts
38
39
  resp, data = http.get("#{url.path}?#{url.query}",
39
40
  "Cookie" => @cookies
40
41
  )
41
-
42
+
42
43
  if resp.code_type != Net::HTTPOK
43
44
  raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
44
45
  end
45
-
46
+
46
47
  parse(data, options)
47
48
  end
48
49
  end
49
-
50
+
50
51
  def login
51
52
  @attempt ||= 0
52
53
  @attempt += 1
53
-
54
+
54
55
  if @attempt == 1
55
56
  @login
56
57
  else
@@ -61,13 +62,13 @@ class Contacts
61
62
  end
62
63
  end
63
64
  end
64
-
65
+
65
66
  def password
66
67
  @password
67
68
  end
68
-
69
+
69
70
  private
70
-
71
+
71
72
  def domain
72
73
  @d ||= URI.parse(self.class.const_get(:URL)).host.sub(/^www\./,'')
73
74
  end
@@ -94,16 +95,16 @@ class Contacts
94
95
  http.start unless http.started?
95
96
  http
96
97
  end
97
-
98
+
98
99
  def cookie_hash_from_string(cookie_string)
99
100
  cookie_string.split(";").map{|i|i.split("=", 2).map{|j|j.strip}}.inject({}){|h,i|h[i[0]]=i[1];h}
100
101
  end
101
-
102
+
102
103
  def parse_cookies(data, existing="")
103
104
  return existing if data.nil?
104
105
 
105
106
  cookies = cookie_hash_from_string(existing)
106
-
107
+
107
108
  data.gsub!(/ ?[\w]+=EXPIRED;/,'')
108
109
  data.gsub!(/ ?expires=(.*?, .*?)[;,$]/i, ';')
109
110
  data.gsub!(/ ?(domain|path)=[\S]*?[;,$]/i,';')
@@ -112,7 +113,7 @@ class Contacts
112
113
  data.gsub!(/(,\s*){2,}/,', ')
113
114
  data.sub!(/^,\s*/,'')
114
115
  data.sub!(/\s*,$/,'')
115
-
116
+
116
117
  data.split(", ").map{|t|t.to_s.split(";").first}.each do |data|
117
118
  k, v = data.split("=", 2).map{|j|j.strip}
118
119
  if cookies[k] && v.empty?
@@ -121,14 +122,14 @@ class Contacts
121
122
  cookies[k] = v
122
123
  end
123
124
  end
124
-
125
+
125
126
  cookies.map{|k,v| "#{k}=#{v}"}.join("; ")
126
127
  end
127
-
128
+
128
129
  def remove_cookie(cookie, cookies)
129
130
  parse_cookies("#{cookie}=", cookies)
130
131
  end
131
-
132
+
132
133
  def post(url, postdata, cookies="", referer="")
133
134
  url = URI.parse(url)
134
135
  http = open_http(url)
@@ -143,12 +144,12 @@ class Contacts
143
144
  cookies = parse_cookies(resp.response['set-cookie'], cookies)
144
145
  forward = resp.response['Location']
145
146
  forward ||= (data =~ /<meta.*?url='([^']+)'/ ? CGI.unescapeHTML($1) : nil)
146
- if (not forward.nil?) && URI.parse(forward).host.nil?
147
- forward = url.scheme.to_s + "://" + url.host.to_s + forward
148
- end
147
+ if (not forward.nil?) && URI.parse(forward).host.nil?
148
+ forward = url.scheme.to_s + "://" + url.host.to_s + forward
149
+ end
149
150
  return data, resp, cookies, forward
150
151
  end
151
-
152
+
152
153
  def get(url, cookies="", referer="")
153
154
  url = URI.parse(url)
154
155
  http = open_http(url)
@@ -161,12 +162,12 @@ class Contacts
161
162
  data = uncompress(resp, data)
162
163
  cookies = parse_cookies(resp.response['set-cookie'], cookies)
163
164
  forward = resp.response['Location']
164
- if (not forward.nil?) && URI.parse(forward).host.nil?
165
- forward = url.scheme.to_s + "://" + url.host.to_s + forward
166
- end
165
+ if (not forward.nil?) && URI.parse(forward).host.nil?
166
+ forward = url.scheme.to_s + "://" + url.host.to_s + forward
167
+ end
167
168
  return data, resp, cookies, forward
168
169
  end
169
-
170
+
170
171
  def uncompress(resp, data)
171
172
  case resp.response['content-encoding']
172
173
  when 'gzip'
@@ -184,27 +185,32 @@ class Contacts
184
185
  data
185
186
  end
186
187
  end
187
-
188
+
188
189
  class ContactsError < StandardError
189
190
  end
190
-
191
+
191
192
  class AuthenticationError < ContactsError
192
193
  end
193
194
 
194
195
  class ConnectionError < ContactsError
195
196
  end
196
-
197
+
197
198
  class TypeNotFound < ContactsError
198
199
  end
199
-
200
- def self.new(type, login, password, options={})
200
+
201
+ def self.new(type, login, password="", secret_key="", options={})
202
+ if !password.nil? && password != '' && !secret_key.nil? && secret_key != ''
203
+ password = Encryptor.decrypt(URI.unescape(password), :key => secret_key)
204
+ end
201
205
  if TYPES.include?(type.to_s.intern)
202
206
  TYPES[type.to_s.intern].new(login, password, options)
207
+ elsif FILETYPES.include?(type.to_s.intern)
208
+ FILETYPES[type.to_s.intern].new(login)
203
209
  else
204
- raise TypeNotFound, "#{type.inspect} is not a valid type, please choose one of the following: #{TYPES.keys.inspect}"
210
+ raise TypeNotFound, "#{type.inspect} is not a valid type, please choose one of the following: #{TYPES.keys.inspect} or #{FILETYPES.keys.inspect}"
205
211
  end
206
212
  end
207
-
213
+
208
214
  def self.guess(login, password, options={})
209
215
  TYPES.inject([]) do |a, t|
210
216
  begin
@@ -27,9 +27,6 @@ class Contacts
27
27
  rescue GData::Client::AuthorizationError => e
28
28
  raise AuthenticationError, "Username or password are incorrect"
29
29
  end
30
-
31
- private
32
-
33
- TYPES[:gmail] = Gmail
34
30
  end
35
- end
31
+ TYPES[:gmail] = Gmail
32
+ end
@@ -3,19 +3,19 @@ class Contacts
3
3
  URL = "https://login.live.com/login.srf?id=2"
4
4
  OLD_CONTACT_LIST_URL = "http://%s/cgi-bin/addresses"
5
5
  NEW_CONTACT_LIST_URL = "http://%s/mail/GetContacts.aspx"
6
- CONTACT_LIST_URL = "http://mpeople.live.com/default.aspx?pg=0"
6
+ CONTACT_LIST_URL = "http://mpeople.live.com/default.aspx?pg=0"
7
7
  COMPOSE_URL = "http://%s/cgi-bin/compose?"
8
8
  PROTOCOL_ERROR = "Hotmail has changed its protocols, please upgrade this library first. If that does not work, report this error at http://rubyforge.org/forum/?group_id=2693"
9
9
  PWDPAD = "IfYouAreReadingThisYouHaveTooMuchFreeTime"
10
10
  MAX_HTTP_THREADS = 8
11
-
11
+
12
12
  def real_connect
13
13
  data, resp, cookies, forward = get(URL)
14
14
  old_url = URL
15
15
  until forward.nil?
16
16
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
17
17
  end
18
-
18
+
19
19
  postdata = "PPSX=%s&PwdPad=%s&login=%s&passwd=%s&LoginOptions=2&PPFT=%s" % [
20
20
  CGI.escape(data.split("><").grep(/PPSX/).first[/=\S+$/][2..-3]),
21
21
  PWDPAD[0...(PWDPAD.length-@password.length)],
@@ -23,15 +23,15 @@ class Contacts
23
23
  CGI.escape(password),
24
24
  CGI.escape(data.split("><").grep(/PPFT/).first[/=\S+$/][2..-3])
25
25
  ]
26
-
26
+
27
27
  form_url = data.split("><").grep(/form/).first.split[5][8..-2]
28
28
  data, resp, cookies, forward = post(form_url, postdata, cookies)
29
-
29
+
30
30
  old_url = form_url
31
31
  until cookies =~ /; PPAuth=/ || forward.nil?
32
32
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
33
33
  end
34
-
34
+
35
35
  if data.index("The e-mail address or password is incorrect")
36
36
  raise AuthenticationError, "Username and password do not match"
37
37
  elsif data != ""
@@ -39,12 +39,12 @@ class Contacts
39
39
  elsif cookies == ""
40
40
  raise ConnectionError, PROTOCOL_ERROR
41
41
  end
42
-
42
+
43
43
  data, resp, cookies, forward = get("http://mail.live.com/mail", cookies)
44
44
  until forward.nil?
45
45
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
46
46
  end
47
-
47
+
48
48
  @domain = URI.parse(old_url).host
49
49
  @cookies = cookies
50
50
  rescue AuthenticationError => m
@@ -54,38 +54,38 @@ class Contacts
54
54
  raise m
55
55
  end
56
56
  end
57
-
57
+
58
58
  def contacts(options = {})
59
59
  if connected?
60
60
  url = URI.parse(contact_list_url)
61
61
  data, resp, cookies, forward = get( contact_list_url, @cookies )
62
-
62
+
63
63
  if resp.code_type != Net::HTTPOK
64
64
  raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
65
65
  end
66
-
66
+
67
67
  @contacts = []
68
68
  build_contacts = []
69
69
  go = true
70
70
  index = 0
71
-
71
+
72
72
  while(go) do
73
73
  go = false
74
74
  url = URI.parse(get_contact_list_url(index))
75
75
  http = open_http(url)
76
76
  resp, data = http.get(get_contact_list_url(index), "Cookie" => @cookies)
77
-
77
+
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
-
81
- raw_html = resp.body.grep(/(?:e|dn)lk[0-9]+/)
80
+
81
+ raw_html = resp.body.split("\n").grep(/(?:e|dn)lk[0-9]+/)
82
82
  raw_html.delete_at 0
83
- raw_html.inject do |memo, row|
83
+ raw_html.inject('') do |memo, row|
84
84
  c_info = row.match(/(e|dn)lk([0-9])+/)
85
-
85
+
86
86
  # Same contact, or different?
87
87
  build_contacts << [] if memo != c_info[2]
88
-
88
+
89
89
  # Grab info
90
90
  case c_info[1]
91
91
  when "e" # Email
@@ -93,32 +93,30 @@ class Contacts
93
93
  when "dn" # Name
94
94
  build_contacts.last[0] = row.match(/<a[^>]*>(.+)<\/a>/)[1]
95
95
  end
96
-
96
+
97
97
  # Set memo to contact id
98
98
  c_info[2]
99
99
  end
100
-
100
+
101
101
  go = resp.body.include?("ContactList_next")
102
102
  index += 1
103
103
  end
104
-
104
+
105
105
  build_contacts.each do |contact|
106
106
  unless contact[1].nil?
107
107
  # Only return contacts with email addresses
108
108
  contact[1] = CGI::unescape(contact[1])
109
+ contact[1] = contact[1].gsub(/&amp;ru.*/, '').gsub(/%40/, '@')
109
110
  @contacts << contact
110
111
  end
111
112
  end
112
113
  return @contacts
113
114
  end
114
115
  end
115
-
116
- def get_contact_list_url(index)
116
+
117
+ def get_contact_list_url(index)
117
118
  "http://mpeople.live.com/default.aspx?pg=#{index}"
118
119
  end
119
-
120
- private
121
-
122
- TYPES[:hotmail] = Hotmail
123
120
  end
124
- end
121
+ TYPES[:hotmail] = Hotmail
122
+ end
@@ -61,16 +61,12 @@ class Contacts
61
61
  if resp.code_type != Net::HTTPOK
62
62
  raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
63
63
  end
64
-
65
- parse data
66
-
67
- #parse more_data
68
-
64
+
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,28 +77,25 @@ 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
88
-
84
+
89
85
  @contacts
90
86
  end
91
87
  end
92
88
 
93
89
  private
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(" "), contact["email"]]
96
+ end if data =~ /^\{"response":/
97
+ @contacts
104
98
  end
105
-
106
99
  end
107
100
 
108
101
  TYPES[:yahoo] = Yahoo
data/lib/contacts.rb CHANGED
@@ -1,11 +1,29 @@
1
1
  $:.unshift(File.dirname(__FILE__)+"/contacts/")
2
2
 
3
+ ## Use ActiveSupport's version of JSON if available
4
+ #if Object.const_defined?('ActiveSupport') && ActiveSupport.const_defined?('JSON')
5
+ # module ActiveSupportJsonParseFunction
6
+ # def parse(i)
7
+ # ActiveSupport::JSON.decode(i)
8
+ # end
9
+ # end
10
+ # # newer versions of ActiveSupport define a root JSON module to extend...
11
+ # if Object.const_defined?('JSON')
12
+ # JSON.send(:extend, ActiveSupportJsonParseFunction)
13
+ # else
14
+ # # ... older need it defined from scratch
15
+ # class JSON
16
+ # extend ActiveSupportJsonParseFunction
17
+ # end
18
+ # end
19
+ #else
20
+ # require 'json/add/rails'
21
+ #end
22
+
3
23
  require 'rubygems'
4
24
 
25
+ require 'json_picker'
5
26
  require 'base'
6
27
  require 'gmail'
7
28
  require 'hotmail'
8
29
  require 'yahoo'
9
- require 'plaxo'
10
- require 'aol'
11
- require 'json_picker'
metadata CHANGED
@@ -1,21 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toferboy-contacts
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
5
- prerelease: false
6
- segments:
7
- - 1
8
- - 2
9
- - 3
10
- version: 1.2.3
4
+ prerelease:
5
+ version: 1.4.1
11
6
  platform: ruby
12
7
  authors:
13
8
  - Lucas Carlson
9
+ - Paperless
14
10
  autorequire:
15
11
  bindir: bin
16
12
  cert_chain: []
17
13
 
18
- date: 2010-01-20 00:00:00 -08:00
14
+ date: 2010-09-20 00:00:00 -07:00
19
15
  default_executable:
20
16
  dependencies:
21
17
  - !ruby/object:Gem::Dependency
@@ -26,32 +22,44 @@ dependencies:
26
22
  requirements:
27
23
  - - ">="
28
24
  - !ruby/object:Gem::Version
29
- hash: 17
30
- segments:
31
- - 1
32
- - 1
33
- - 1
34
25
  version: 1.1.1
35
26
  type: :runtime
36
27
  version_requirements: *id001
37
28
  - !ruby/object:Gem::Dependency
38
- name: gdata
29
+ name: gdata19
39
30
  prerelease: false
40
31
  requirement: &id002 !ruby/object:Gem::Requirement
41
32
  none: false
42
33
  requirements:
43
34
  - - ">="
44
35
  - !ruby/object:Gem::Version
45
- hash: 17
46
- segments:
47
- - 1
48
- - 1
49
- - 1
50
- version: 1.1.1
36
+ version: "0"
51
37
  type: :runtime
52
38
  version_requirements: *id002
53
- description: A universal interface to grab contact list information from various providers including Yahoo, AOL, Gmail, Hotmail, and Plaxo.
54
- email: lucas@rufy.com
39
+ - !ruby/object:Gem::Dependency
40
+ name: hpricot
41
+ prerelease: false
42
+ requirement: &id003 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id003
50
+ - !ruby/object:Gem::Dependency
51
+ name: encryptor
52
+ prerelease: false
53
+ requirement: &id004 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ type: :runtime
60
+ version_requirements: *id004
61
+ description: A universal interface to grab contact list information from various providers including Outlook, Address Book, Yahoo, AOL, Gmail, Hotmail, and Plaxo.
62
+ email:
55
63
  executables: []
56
64
 
57
65
  extensions: []
@@ -67,12 +75,12 @@ files:
67
75
  - lib/contacts/base.rb
68
76
  - lib/contacts/json_picker.rb
69
77
  - lib/contacts/gmail.rb
70
- - lib/contacts/aol.rb
78
+ - lib/contacts/aol_importer.rb
71
79
  - lib/contacts/hotmail.rb
72
80
  - lib/contacts/plaxo.rb
73
81
  - lib/contacts/yahoo.rb
74
82
  has_rdoc: true
75
- homepage: http://github.com/cardmagic/contacts
83
+ homepage: http://github.com/paperlesspost/contacts
76
84
  licenses: []
77
85
 
78
86
  post_install_message:
@@ -85,25 +93,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
93
  requirements:
86
94
  - - ">="
87
95
  - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
96
  version: "0"
92
97
  required_rubygems_version: !ruby/object:Gem::Requirement
93
98
  none: false
94
99
  requirements:
95
100
  - - ">="
96
101
  - !ruby/object:Gem::Version
97
- hash: 3
98
- segments:
99
- - 0
100
102
  version: "0"
101
103
  requirements: []
102
104
 
103
105
  rubyforge_project:
104
- rubygems_version: 1.3.7
106
+ rubygems_version: 1.6.2
105
107
  signing_key:
106
108
  specification_version: 3
107
- summary: A universal interface to grab contact list information from various providers including Yahoo, AOL, Gmail, Hotmail, and Plaxo.
109
+ summary: A universal interface to grab contact list information from various providers including Outlook, Address Book, Yahoo, AOL, Gmail, Hotmail, and Plaxo.
108
110
  test_files: []
109
111