contacts 1.0.6 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|