contacts 1.0.6 → 1.0.7

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/README CHANGED
@@ -30,8 +30,13 @@ Notice there are three ways to use this library so that you can limit the use as
30
30
 
31
31
  See the examples/ directory.
32
32
 
33
- == Authors
33
+ == Authors
34
+
34
35
  * Lucas Carlson from MOG (mailto:lucas@rufy.com) - http://mog.com
35
36
 
37
+ == Contributors
38
+
39
+ * Britt Selvitelle from Twitter (mailto:anotherbritt@gmail.com) - http://twitter.com
40
+
36
41
  This library is released under the terms of the BSD.
37
42
 
data/lib/contacts/base.rb CHANGED
@@ -8,7 +8,7 @@ require "thread"
8
8
 
9
9
  class Contacts
10
10
  TYPES = {}
11
- VERSION = "1.0.6"
11
+ VERSION = "1.0.7"
12
12
 
13
13
  class Base
14
14
  def initialize(login, password)
@@ -27,7 +27,7 @@ class Contacts
27
27
  @cookies && !@cookies.empty?
28
28
  end
29
29
 
30
- def contacts
30
+ def contacts(options = {})
31
31
  return @contacts if @contacts
32
32
  if connected?
33
33
  url = URI.parse(contact_list_url)
@@ -40,7 +40,7 @@ class Contacts
40
40
  raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
41
41
  end
42
42
 
43
- parse data
43
+ parse(data, options)
44
44
  end
45
45
  end
46
46
 
@@ -5,19 +5,19 @@ class Contacts
5
5
  URL = "https://mail.google.com/mail/"
6
6
  LOGIN_URL = "https://www.google.com/accounts/ServiceLoginAuth"
7
7
  LOGIN_REFERER_URL = "https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%3Fui%3Dhtml%26zy%3Dl&ltmpl=yj_blanco&ltmplcache=2&hl=en"
8
- CONTACT_LIST_URL = "https://mail.google.com/mail/?view=cl&search=contacts&pnl=a"
8
+ CONTACT_LIST_URL = "https://mail.google.com/mail/contacts/data/contacts?thumb=true&show=ALL&enums=true&psort=Name&max=10000&out=js&rf=&jsx=true"
9
9
  PROTOCOL_ERROR = "Gmail has changed its protocols, please upgrade this library first. If that does not work, contact lucas@rufy.com with this error"
10
10
 
11
11
  def real_connect
12
12
  postdata = "ltmpl=yj_blanco"
13
- postdata += "&continue=#{CGI.escape(URL)}"
13
+ postdata += "&continue=%s" % CGI.escape(URL)
14
14
  postdata += "&ltmplcache=2"
15
15
  postdata += "&service=mail"
16
16
  postdata += "&rm=false"
17
17
  postdata += "&ltmpl=yj_blanco"
18
18
  postdata += "&hl=en"
19
- postdata += "&Email=#{CGI.escape(login)}"
20
- postdata += "&Passwd=#{CGI.escape(password)}"
19
+ postdata += "&Email=%s" % CGI.escape(login)
20
+ postdata += "&Passwd=%s" % CGI.escape(password)
21
21
  postdata += "&rmShown=1"
22
22
  postdata += "&null=Sign+in"
23
23
 
@@ -41,41 +41,34 @@ class Contacts
41
41
  raise ConnectionError, PROTOCOL_ERROR
42
42
  end
43
43
 
44
- until forward.nil?
45
- data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
46
- end
47
44
  cookies = remove_cookie("LSID", cookies)
48
45
  cookies = remove_cookie("GV", cookies)
49
-
50
- if resp.code_type != Net::HTTPOK
51
- raise ConnectionError, PROTOCOL_ERROR
52
- end
53
-
46
+
54
47
  @cookies = cookies
55
48
  end
56
49
 
57
50
  private
58
51
 
59
- def parse(data)
60
- data.gsub!("\n","")
61
- data.gsub!("D([", "\nD([")
62
- data.gsub!("]);", "]);\n")
63
- data.gsub!("u003d", "=")
64
- data.gsub!("u002f", "/")
52
+ def parse(data, options)
53
+ data.gsub!(/^while \(true\); &&&START&&&/, '')
54
+ data.gsub!(/ &&&END&&&$/, '')
55
+ @contacts = JSON.parse(data)['Body']['Contacts']
65
56
 
66
- parsed_data = []
67
- data.scan(%r{D\(\[(.*)\]\)}) do |match|
68
- parsed_data << JSON.parse("[#{match[0]}]") rescue next
69
- end
57
+ # Determine in which format to return the data.
70
58
 
71
- @contacts = parsed_data.select{|d| d[0] == "cl"}.inject([]) do |a,d|
72
- a.concat(d.inject([]) do |ar,dr|
73
- ar.concat(dr.is_a?(Array) && dr[4] && !dr[4].empty? ? [[dr[3],dr[4]]] : [])
74
- end)
59
+ # Return the full JSON Hash.
60
+ return @contacts if(options[:details])
61
+
62
+ # Default format.
63
+ # ['Name', 'Email1', 'Email2', ...]
64
+ @contacts = @contacts.map do |c|
65
+ name, emails = c.values_at "Name", "Emails"
66
+ emails = emails.first.values
67
+ [name, emails].flatten
75
68
  end
76
69
  end
77
70
 
78
71
  end
79
72
 
80
73
  TYPES[:gmail] = Gmail
81
- end
74
+ end
@@ -9,8 +9,6 @@ class Contacts
9
9
  MAX_HTTP_THREADS = 8
10
10
 
11
11
  def real_connect
12
- @use_new_contact_url = false
13
-
14
12
  data, resp, cookies, forward = get(URL)
15
13
 
16
14
  old_url = URL
@@ -18,10 +16,13 @@ class Contacts
18
16
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
19
17
  end
20
18
 
21
- postdata = "PPSX=#{CGI.escape(data.split("><").grep(/PPSX/).first[/=\S+$/][2..-3])}&"
22
- postdata += "PwdPad=#{PWDPAD[0...(PWDPAD.length-@password.length)]}&"
23
- postdata += "login=#{CGI.escape(login)}&passwd=#{CGI.escape(password)}&LoginOptions=2&"
24
- postdata += "PPFT=#{CGI.escape(data.split("><").grep(/PPFT/).first[/=\S+$/][2..-3])}"
19
+ postdata = "PPSX=%s&PwdPad=%s&login=%s&passwd=%s&LoginOptions=2&PPFT=%s" % [
20
+ CGI.escape(data.split("><").grep(/PPSX/).first[/=\S+$/][2..-3]),
21
+ PWDPAD[0...(PWDPAD.length-@password.length)],
22
+ CGI.escape(login),
23
+ CGI.escape(password),
24
+ CGI.escape(data.split("><").grep(/PPFT/).first[/=\S+$/][2..-3])
25
+ ]
25
26
 
26
27
  form_url = data.split("><").grep(/form/).first.split[5][8..-2]
27
28
  data, resp, cookies, forward = post(form_url, postdata, cookies)
@@ -38,27 +39,31 @@ class Contacts
38
39
  until forward.nil?
39
40
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
40
41
  end
41
-
42
- if resp.code_type != Net::HTTPOK
43
- raise ConnectionError, PROTOCOL_ERROR
44
- end
45
42
 
46
- forward = "http://www.hotmail.msn.com/cgi-bin/sbox"
43
+ =begin
44
+ if data =~ %r{action="(.*?)"}
45
+ forward = $1
46
+ puts forward
47
+ napexp = CGI.escape(data.to_s[/id="NAPExp" value="(.*?)"/][19...-1])
48
+ nap = CGI.escape(data.to_s[/id="NAP" value="(.*?)"/][16...-1])
49
+ anon = CGI.escape(data.to_s[/id="ANON" value="(.*?)"/][17...-1])
50
+ anonexp = CGI.escape(data.to_s[/id="ANONExp" value="(.*?)"/][20...-1])
51
+ t = CGI.escape(data.to_s[/id="t" value="(.*?)"/][14...-1])
52
+
53
+ postdata = "NAPExp=%s&NAP=%s&ANON=%s&ANONExp=%s&t=%s" % [ napexp, nap, anon, anonexp, t ]
54
+ puts postdata
55
+ data, resp, cookies, forward, old_url = post(forward, postdata, cookies, old_url) + [forward]
56
+ end
47
57
 
48
58
  until forward.nil?
49
59
  data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
50
60
  end
61
+ =end
51
62
 
52
- if resp.code_type != Net::HTTPOK
53
- raise ConnectionError, PROTOCOL_ERROR
54
- elsif old_url.include?('login.live.com')
55
- data, resp, cookies, forward, old_url = get("http://mail.live.com/mail", cookies)
56
- data, resp, cookies, forward, old_url = get(forward, cookies)
57
- old_url = forward
58
- @use_new_contact_url = true
59
- end
63
+ data, resp, cookies, forward, old_url = get("http://mail.live.com/mail", cookies)
64
+ data, resp, cookies, forward, old_url = get(forward, cookies)
60
65
 
61
- @domain = URI.parse(old_url).host
66
+ @domain = URI.parse(forward).host
62
67
  @cookies = cookies
63
68
  rescue AuthenticationError => m
64
69
  if @attempt == 1
@@ -71,7 +76,7 @@ class Contacts
71
76
  private
72
77
 
73
78
  def contact_list_url
74
- (@use_new_contact_url ? NEW_CONTACT_LIST_URL : OLD_CONTACT_LIST_URL) % @domain
79
+ NEW_CONTACT_LIST_URL % @domain
75
80
  end
76
81
 
77
82
  def follow_email(data, id, contacts_slot)
@@ -93,48 +98,12 @@ class Contacts
93
98
  @contacts[contacts_slot][1] = e[1] if e[1].match(/@/)
94
99
  end
95
100
 
96
- def parse(data)
97
- if @use_new_contact_url
98
- data = CSV.parse(data)
99
- col_names = data.shift
100
- @contacts = data.map do |person|
101
- [[person[1], person[2], person[3]].delete_if{|i|i.nil?}.join(" "), person[46]] unless person[46].nil?
102
- end.compact
103
- else
104
- chunks = data.split('id="hotmail"')
105
- prev = chunks.delete_at(0)
106
-
107
- queue = Queue.new
108
- threads = []
109
- @contacts = []
110
- chunks.each do |chunk|
111
- name = chunk.split('return false;">')[1].split('</a>')[0] rescue nil
112
- email = chunk.split('return false;">')[2].split('</a>')[0] rescue nil
113
- unless email && email != "more"
114
- prev = chunk
115
- next
116
- end
117
- next_slot = @contacts.size
118
- @contacts[next_slot] = [name, email]
119
- if email.match(/\.\.\.$/)
120
- if m = prev.match(/\s+id="([A-Za-z0-9\-]+)"/)
121
- queue.push([m[1], next_slot])
122
- if threads.size < MAX_HTTP_THREADS
123
- threads.push(Thread.new {
124
- while x = queue.pop
125
- follow_email(data, *x)
126
- end
127
- })
128
- end
129
- end
130
- end
131
- prev = chunk
132
- end
133
-
134
- threads.each { queue.push(nil) }
135
- threads.each { |t| t.join }
136
- @contacts
137
- end
101
+ def parse(data, options={})
102
+ data = CSV.parse(data)
103
+ col_names = data.shift
104
+ @contacts = data.map do |person|
105
+ [[person[1], person[2], person[3]].delete_if{|i|i.nil?}.join(" "), person[46]] unless person[46].nil?
106
+ end.compact
138
107
  end
139
108
 
140
109
  end
@@ -68,7 +68,7 @@ class Contacts
68
68
 
69
69
  private
70
70
 
71
- def parse(data)
71
+ def parse(data, options={})
72
72
  data = CSV.parse(data)
73
73
  col_names = data.shift
74
74
  @contacts = data.map do |person|
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: contacts
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.6
7
- date: 2007-10-29 00:00:00 -07:00
6
+ version: 1.0.7
7
+ date: 2007-11-20 00:00:00 -08:00
8
8
  summary: Ridiculously easy contact list information from various providers including Yahoo, Gmail, and Hotmail
9
9
  require_paths:
10
10
  - lib