yahoo.rb
4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
class Contacts
class Yahoo < Base
URL = "http://mail.yahoo.com/"
LOGIN_URL = "https://login.yahoo.com/config/login"
ADDRESS_BOOK_URL = "http://address.mail.yahoo.com/?.rand=430244936"
CONTACT_LIST_URL = "http://address.mail.yahoo.com/?_src=&_crumb=crumb&sortfield=3&bucket=1&scroll=1&VPC=social_list&.r=time"
PROTOCOL_ERROR = "Yahoo 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"
def real_connect
postdata = ".tries=2&.src=ym&.md5=&.hash=&.js=&.last=&promo=&.intl=us&.bypass="
postdata += "&.partner=&.u=4eo6isd23l8r3&.v=0&.challenge=gsMsEcoZP7km3N3NeI4mX"
postdata += "kGB7zMV&.yplus=&.emailCode=&pkg=&stepid=&.ev=&hasMsgr=1&.chkP=Y&."
postdata += "done=#{CGI.escape(URL)}&login=#{CGI.escape(login)}&passwd=#{CGI.escape(password)}"
data, resp, cookies, forward = post(LOGIN_URL, postdata)
if data.index("Invalid ID or password") || data.index("This ID is not yet taken")
raise AuthenticationError, "Username and password do not match"
elsif data.index("Sign in") && data.index("to Yahoo!")
raise AuthenticationError, "Required field must not be blank"
elsif !data.match(/uncompressed\/chunked/)
raise ConnectionError, PROTOCOL_ERROR
elsif cookies == ""
raise ConnectionError, PROTOCOL_ERROR
end
data, resp, cookies, forward = get(forward, cookies, LOGIN_URL)
if resp.code_type != Net::HTTPOK
raise ConnectionError, PROTOCOL_ERROR
end
@cookies = cookies
end
def contacts
return @contacts if @contacts
if connected?
# first, get the addressbook site with the new crumb parameter
url = URI.parse(address_book_url)
http = open_http(url)
resp, data = http.get("#{url.path}?#{url.query}",
"Cookie" => @cookies
)
if resp.code_type != Net::HTTPOK
raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
end
crumb = data.to_s[/dotCrumb: '(.*?)'/][13...-1]
# now proceed with the new ".crumb" parameter to get the csv data
url = URI.parse(contact_list_url.sub("_crumb=crumb","_crumb=#{crumb}").sub("time", Time.now.to_f.to_s.sub(".","")[0...-2]))
http = open_http(url)
resp, more_data = http.get("#{url.path}?#{url.query}",
"Cookie" => @cookies,
"X-Requested-With" => "XMLHttpRequest",
"Referer" => address_book_url
)
if resp.code_type != Net::HTTPOK
raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
end
parse data
parse more_data
if more_data =~ /"TotalABContacts":(\d+)/
total = $1.to_i
((total / 50)).times do |i|
# now proceed with the new ".crumb" parameter to get the csv data
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]))
http = open_http(url)
resp, more_data = http.get("#{url.path}?#{url.query}",
"Cookie" => @cookies,
"X-Requested-With" => "XMLHttpRequest",
"Referer" => address_book_url
)
if resp.code_type != Net::HTTPOK
raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
end
parse more_data
end
end
@contacts
end
end
private
def parse(data, options={})
@contacts ||= []
if data =~ /var InitialContacts = (\[.*?\])/
@contacts += Contacts.parse_json($1).select{|contact|!contact["email"].to_s.empty?}.map{|contact|[contact["contactName"], contact["email"]]}
elsif data =~ /^\{"response":/
@contacts += Contacts.parse_json(data)["response"]["ResultSet"]["Contacts"].to_a.select{|contact|!contact["email"].to_s.empty?}.map{|contact|[contact["contactName"], contact["email"]]}
else
@contacts
end
end
end
TYPES[:yahoo] = Yahoo
end