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 +6 -1
- data/lib/contacts/base.rb +3 -3
- data/lib/contacts/gmail.rb +20 -27
- data/lib/contacts/hotmail.rb +32 -63
- data/lib/contacts/yahoo.rb +1 -1
- metadata +2 -2
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.
|
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
|
43
|
+
parse(data, options)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
data/lib/contacts/gmail.rb
CHANGED
@@ -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<mpl=yj_blanco<mplcache=2&hl=en"
|
8
|
-
CONTACT_LIST_URL = "https://mail.google.com/mail
|
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
|
13
|
+
postdata += "&continue=%s" % CGI.escape(URL)
|
14
14
|
postdata += "<mplcache=2"
|
15
15
|
postdata += "&service=mail"
|
16
16
|
postdata += "&rm=false"
|
17
17
|
postdata += "<mpl=yj_blanco"
|
18
18
|
postdata += "&hl=en"
|
19
|
-
postdata += "&Email
|
20
|
-
postdata += "&Passwd
|
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!(
|
61
|
-
data.gsub!(
|
62
|
-
|
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
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
data/lib/contacts/hotmail.rb
CHANGED
@@ -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
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
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
|
-
|
53
|
-
|
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(
|
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
|
-
|
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
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
data/lib/contacts/yahoo.rb
CHANGED
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.
|
7
|
-
date: 2007-
|
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
|