aeden-contacts 0.2.19 → 0.2.20
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/VERSION.yml +1 -1
- data/lib/contacts.rb +2 -2
- data/lib/contacts/windows_live.rb +39 -22
- data/lib/contacts/yahoo.rb +93 -13
- data/spec/feeds/wl_full_contacts.xml +78 -0
- data/spec/feeds/yh_contacts.txt +27 -68
- data/spec/windows_live/windows_live_spec.rb +16 -10
- data/spec/yahoo/yahoo_spec.rb +20 -12
- metadata +5 -3
data/VERSION.yml
CHANGED
data/lib/contacts.rb
CHANGED
@@ -6,8 +6,8 @@ module Contacts
|
|
6
6
|
|
7
7
|
# An object that represents a single contact
|
8
8
|
class Contact
|
9
|
-
attr_reader
|
10
|
-
attr_accessor :name, :username, :service_id, :note
|
9
|
+
attr_reader :organizations, :firstname, :lastname
|
10
|
+
attr_accessor :name, :username, :service_id, :note, :emails, :ims,:phones, :addresses
|
11
11
|
|
12
12
|
def initialize(email, name = nil, username = nil, firstname = nil, lastname = nil)
|
13
13
|
@emails = []
|
@@ -126,7 +126,7 @@ module Contacts
|
|
126
126
|
|
127
127
|
response = nil
|
128
128
|
http.start do |http|
|
129
|
-
request = Net::HTTP::Get.new("/users/@L@#{@consent_token.locationid}/rest/
|
129
|
+
request = Net::HTTP::Get.new("/users/@L@#{@consent_token.locationid}/rest/LiveContacts", {"Authorization" => "DelegatedToken dt=\"#{@consent_token.delegationtoken}\""})
|
130
130
|
response = http.request(request)
|
131
131
|
end
|
132
132
|
|
@@ -141,32 +141,49 @@ module Contacts
|
|
141
141
|
#
|
142
142
|
def self.parse_xml(xml)
|
143
143
|
doc = Hpricot::XML(xml)
|
144
|
-
|
145
144
|
contacts = []
|
146
|
-
doc.search('/
|
147
|
-
email = contact.at('/preferredemail').inner_text
|
148
|
-
email.strip!
|
149
|
-
|
150
|
-
first_name = last_name = nil
|
151
|
-
if first_name = contact.at('/profiles/personal/firstname')
|
152
|
-
first_name = first_name.inner_text.strip
|
153
|
-
end
|
154
|
-
|
155
|
-
if last_name = contact.at('/profiles/personal/lastname')
|
156
|
-
last_name = last_name.inner_text.strip
|
157
|
-
end
|
145
|
+
doc.search('/LiveContacts/Contacts/Contact') do |contact|
|
158
146
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
147
|
+
contact_id = text_value contact, "ID"
|
148
|
+
|
149
|
+
first_name = text_value contact, "Profiles/Personal/FirstName"
|
150
|
+
last_name = text_value contact, "Profiles/Personal/LastName"
|
151
|
+
name = "#{first_name} #{last_name}".strip
|
152
|
+
emails = contact.search('Emails/Email').collect {|e| text_value e, "Address"}
|
153
|
+
|
154
|
+
phones = contact.search('Phones/Phone').collect do |e|
|
155
|
+
type=convert_type(text_value(e, "PhoneType"))
|
156
|
+
{ "type" => type, "value" => (text_value e, "Number") }
|
157
|
+
end
|
158
|
+
|
159
|
+
addresses = contact.search('Locations/Location').collect do |e|
|
160
|
+
street = text_value(e, "StreetLine")
|
161
|
+
postal_code = text_value(e, "PostalCode")
|
162
|
+
sub_division = text_value(e, "Subdivision")
|
163
|
+
city = text_value(e, "PrimaryCity")
|
164
|
+
country_code = text_value(e, "CountryRegion")
|
165
|
+
formatted = [street, city, sub_division, postal_code, country_code].compact.join(", ")
|
166
|
+
type = convert_type(text_value(e, "LocationType"))
|
167
|
+
{ "formatted" => formatted, "type" => type, "streetAddress" => street, "locality" => city, "region" => sub_division, "postalCode" => postal_code, "country" => country_code}
|
168
|
+
end
|
167
169
|
|
170
|
+
new_contact = Contact.new(nil, name, nil, first_name, last_name)
|
171
|
+
new_contact.emails = emails
|
172
|
+
new_contact.phones = phones
|
173
|
+
new_contact.addresses = addresses
|
174
|
+
new_contact.service_id = contact_id
|
175
|
+
contacts << new_contact
|
176
|
+
end
|
168
177
|
return contacts
|
169
178
|
end
|
179
|
+
|
180
|
+
def self.text_value(elem,path)
|
181
|
+
elem.at(path).inner_text rescue nil
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.convert_type(t)
|
185
|
+
{"personal" => "home", "business" => "work"}[t.downcase] || "other"
|
186
|
+
end
|
170
187
|
end
|
171
188
|
|
172
189
|
end
|
data/lib/contacts/yahoo.rb
CHANGED
@@ -58,7 +58,7 @@ module Contacts
|
|
58
58
|
AUTH_PATH = "/WSLogin/V1/wslogin?appid=#appid&ts=#ts"
|
59
59
|
CREDENTIAL_PATH = "/WSLogin/V1/wspwtoken_login?appid=#appid&ts=#ts&token=#token"
|
60
60
|
ADDRESS_BOOK_DOMAIN = "address.yahooapis.com"
|
61
|
-
ADDRESS_BOOK_PATH = "/v1/searchContacts?format=json&fields=
|
61
|
+
ADDRESS_BOOK_PATH = "/v1/searchContacts?format=json&fields=all&appid=#appid&WSSID=#wssid"
|
62
62
|
CONFIG_FILE = File.dirname(__FILE__) + '/../config/contacts.yml'
|
63
63
|
|
64
64
|
attr_reader :appid, :secret, :token, :wssid, :cookie
|
@@ -213,34 +213,114 @@ module Contacts
|
|
213
213
|
#
|
214
214
|
# ==== Parameters
|
215
215
|
# * json <String>:: A String of user's contacts in JSON format
|
216
|
-
#
|
216
|
+
# "fields": [
|
217
|
+
# {
|
218
|
+
# "type": "phone",
|
219
|
+
# "data": "808 123 1234",
|
220
|
+
# "home": true,
|
221
|
+
# },
|
222
|
+
# {
|
223
|
+
# "type": "email",
|
224
|
+
# "data": "martin.berner@mail.com",
|
225
|
+
# },
|
226
|
+
#
|
227
|
+
# {
|
228
|
+
# "type": "otherid",
|
229
|
+
# "data": "windowslive@msn.com",
|
230
|
+
# "msn": true,
|
231
|
+
# }
|
232
|
+
# ]
|
233
|
+
#
|
217
234
|
def self.parse_contacts(json)
|
218
235
|
contacts = []
|
219
236
|
people = JSON.parse(json)
|
237
|
+
|
220
238
|
people['contacts'].each do |contact|
|
221
239
|
name = nil
|
222
240
|
email = nil
|
223
241
|
firstname = nil
|
224
242
|
lastname = nil
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
243
|
+
|
244
|
+
contact_fields=Yahoo.array_to_hash contact['fields']
|
245
|
+
|
246
|
+
emails = (contact_fields['email'] || []).collect {|e| e['data']}
|
247
|
+
ims = (contact_fields['otherid'] || []).collect { |im| get_type_value(im) }
|
248
|
+
phones = (contact_fields['phone'] || []).collect { |phone| get_type_value(phone) }
|
249
|
+
addresses = (contact_fields['address'] || []).collect do |address|
|
250
|
+
type=get_type(address)
|
251
|
+
type = {"home" => "home", "work" => "work"}[type.downcase] || "other"
|
252
|
+
value = [address['street'], address['city'], address['state'], address['zip'], address['country']].compact.join(", ")
|
253
|
+
{"type" => type, "value" => value}
|
254
|
+
end
|
255
|
+
|
256
|
+
name_field=(contact_fields['name'] || [])
|
257
|
+
|
258
|
+
# if name is blank, try go for the yahoo id, and if that's blank too, ignore the record altogether (probably a mailing list)
|
259
|
+
if (name_field.empty?)
|
260
|
+
if contact_fields['yahooid']
|
261
|
+
name = contact_fields['yahooid'][0]['data']
|
262
|
+
else
|
263
|
+
next
|
235
264
|
end
|
265
|
+
else
|
266
|
+
name_field = name_field[0]
|
267
|
+
name = "#{name_field['first']} #{name_field['last']}"
|
268
|
+
name.strip!
|
269
|
+
lastname = name_field['last']
|
270
|
+
firstname = name_field['first']
|
236
271
|
end
|
237
|
-
|
272
|
+
|
273
|
+
yahoo_contact = Contact.new(nil, name, nil, firstname, lastname)
|
274
|
+
yahoo_contact.emails = emails
|
275
|
+
yahoo_contact.ims = ims
|
276
|
+
yahoo_contact.phones = phones
|
277
|
+
yahoo_contact.addresses = addresses
|
238
278
|
yahoo_contact.service_id = contact['cid']
|
239
279
|
|
240
280
|
contacts.push yahoo_contact
|
241
281
|
end
|
242
282
|
return contacts
|
243
283
|
end
|
284
|
+
|
285
|
+
#
|
286
|
+
# grab the type field from each array item
|
287
|
+
# and turn it into a "email"=>{}, "phone"=>{} array
|
288
|
+
#
|
289
|
+
private
|
290
|
+
def self.array_to_hash(a)
|
291
|
+
(a || []).inject({}) {|x,y|
|
292
|
+
x[y['type']] ||= []
|
293
|
+
x[y['type']] << y
|
294
|
+
x
|
295
|
+
}
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
# return type/value from a datastructure like
|
300
|
+
# {
|
301
|
+
# "data": "808 456 7890",
|
302
|
+
# "mobile": true
|
303
|
+
# }
|
304
|
+
# -----> "type"=>"mobile", "value"=>"808 456 7890"
|
305
|
+
#
|
306
|
+
def self.get_type_value(hash)
|
307
|
+
type_field = hash.find{ |x| x[1] == true }
|
308
|
+
type = type_field ? type_field[0] : nil
|
309
|
+
{"type" => type, "value" => hash["data"]}
|
310
|
+
end
|
311
|
+
|
312
|
+
#
|
313
|
+
# return just the type from a datastructure like
|
314
|
+
# {
|
315
|
+
# "data": "808 456 7890",
|
316
|
+
# "mobile": true
|
317
|
+
# }
|
318
|
+
# -----> "mobile"
|
319
|
+
#
|
320
|
+
def self.get_type(hash)
|
321
|
+
type_field = hash.find{ |x| x[1] == true }
|
322
|
+
type = type_field ? type_field[0] : nil
|
323
|
+
end
|
244
324
|
|
245
325
|
end
|
246
326
|
class YahooToken
|
@@ -0,0 +1,78 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<LiveContacts>
|
3
|
+
|
4
|
+
<Contacts>
|
5
|
+
<Contact>
|
6
|
+
<ID>abc</ID>
|
7
|
+
<WindowsLiveID>beenthere@hotmail.com</WindowsLiveID>
|
8
|
+
|
9
|
+
<Profiles>
|
10
|
+
<Personal>
|
11
|
+
<FirstName>Mia</FirstName>
|
12
|
+
<LastName>Pia</LastName>
|
13
|
+
<UniqueName>mia</UniqueName>
|
14
|
+
</Personal>
|
15
|
+
</Profiles>
|
16
|
+
<Emails>
|
17
|
+
<Email>
|
18
|
+
<ID>1</ID>
|
19
|
+
<EmailType>Personal</EmailType>
|
20
|
+
<Address>mia@hotmail.com</Address>
|
21
|
+
<IsIMEnabled>false</IsIMEnabled>
|
22
|
+
<IsDefault>false</IsDefault>
|
23
|
+
</Email>
|
24
|
+
<Email>
|
25
|
+
<ID>8</ID>
|
26
|
+
<EmailType>WindowsLiveID</EmailType>
|
27
|
+
<Address>othermia@yahoo.com</Address>
|
28
|
+
<IsIMEnabled>true</IsIMEnabled>
|
29
|
+
<IsDefault>false</IsDefault>
|
30
|
+
</Email>
|
31
|
+
</Emails>
|
32
|
+
<Phones>
|
33
|
+
<Phone>
|
34
|
+
<ID>1</ID>
|
35
|
+
<PhoneType>Personal</PhoneType>
|
36
|
+
<Number>(123) 123 1234</Number>
|
37
|
+
<IsIMEnabled>false</IsIMEnabled>
|
38
|
+
<IsDefault>false</IsDefault>
|
39
|
+
</Phone>
|
40
|
+
<Phone>
|
41
|
+
<ID>3</ID>
|
42
|
+
<PhoneType>Mobile</PhoneType>
|
43
|
+
<Number>(321) 555 1234</Number>
|
44
|
+
<IsIMEnabled>false</IsIMEnabled>
|
45
|
+
<IsDefault>false</IsDefault>
|
46
|
+
</Phone>
|
47
|
+
</Phones>
|
48
|
+
<Locations>
|
49
|
+
<Location>
|
50
|
+
<ID>1</ID>
|
51
|
+
<LocationType>Personal</LocationType>
|
52
|
+
<StreetLine>123 Green St</StreetLine>
|
53
|
+
<PrimaryCity>Middleville</PrimaryCity>
|
54
|
+
<Subdivision>CA</Subdivision>
|
55
|
+
<PostalCode>92123</PostalCode>
|
56
|
+
<CountryRegion>USA</CountryRegion>
|
57
|
+
<IsDefault>false</IsDefault>
|
58
|
+
</Location>
|
59
|
+
</Locations>
|
60
|
+
</Contact>
|
61
|
+
<Contact>
|
62
|
+
<ID>def</ID>
|
63
|
+
<WindowsLiveID>marcus@hotmail.com</WindowsLiveID>
|
64
|
+
<Profiles>
|
65
|
+
<Personal>
|
66
|
+
<UniqueName>marcus</UniqueName>
|
67
|
+
<DisplayName>marietta_ru@hotmail.com</DisplayName>
|
68
|
+
</Personal>
|
69
|
+
</Profiles>
|
70
|
+
<Emails>
|
71
|
+
<Email>
|
72
|
+
<EmailType>WindowsLiveID</EmailType>
|
73
|
+
<Address>marcus@hotmail.com</Address>
|
74
|
+
</Email>
|
75
|
+
</Emails>
|
76
|
+
</Contact>
|
77
|
+
</Contacts>
|
78
|
+
</LiveContacts>
|
data/spec/feeds/yh_contacts.txt
CHANGED
@@ -34,86 +34,45 @@
|
|
34
34
|
"categories":[
|
35
35
|
]
|
36
36
|
},
|
37
|
-
|
38
|
-
"type":"name",
|
39
|
-
"first":"Nina",
|
40
|
-
"last":"Benchimol",
|
41
|
-
"fid":4,
|
42
|
-
"categories":[
|
43
|
-
]
|
44
|
-
}
|
45
|
-
],
|
46
|
-
"cid":5,
|
47
|
-
"categories":[
|
48
|
-
]
|
49
|
-
},
|
50
|
-
{
|
51
|
-
"type":"contact",
|
52
|
-
"fields":[
|
53
|
-
{
|
37
|
+
{
|
54
38
|
"type":"email",
|
55
|
-
"data":"
|
56
|
-
"fid":
|
39
|
+
"data":"nina2@yahoo.com",
|
40
|
+
"fid":5,
|
57
41
|
"categories":[
|
58
42
|
]
|
59
43
|
},
|
60
44
|
{
|
61
45
|
"type":"name",
|
62
|
-
"first":"
|
63
|
-
"last":"
|
64
|
-
"fid":
|
65
|
-
"categories":[
|
66
|
-
]
|
67
|
-
}
|
68
|
-
],
|
69
|
-
"cid":1,
|
70
|
-
"categories":[
|
71
|
-
]
|
72
|
-
},
|
73
|
-
{
|
74
|
-
"type":"contact",
|
75
|
-
"fields":[
|
76
|
-
{
|
77
|
-
"type":"email",
|
78
|
-
"data":"ricardo@poli.usp.br",
|
79
|
-
"fid":11,
|
46
|
+
"first":"Nina",
|
47
|
+
"last":"Benchimol",
|
48
|
+
"fid":4,
|
80
49
|
"categories":[
|
81
50
|
]
|
82
51
|
},
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
52
|
+
{
|
53
|
+
"type": "otherid",
|
54
|
+
"data": "windowslive@msn.com",
|
55
|
+
"msn": true
|
56
|
+
},
|
57
|
+
{
|
58
|
+
"type": "phone",
|
59
|
+
"data": "808 456 7890",
|
60
|
+
"mobile": true
|
61
|
+
},
|
62
|
+
{
|
63
|
+
"type": "address",
|
64
|
+
"street": "123 Home Street",
|
65
|
+
"city": "Super City",
|
66
|
+
"state": "HI",
|
67
|
+
"zip": "96815",
|
68
|
+
"country": "United States",
|
69
|
+
"home": true
|
70
|
+
}
|
91
71
|
],
|
92
|
-
"cid":
|
72
|
+
"cid":5,
|
93
73
|
"categories":[
|
94
74
|
]
|
95
75
|
},
|
96
|
-
{
|
97
|
-
"type":"contact",
|
98
|
-
"fields":[
|
99
|
-
{
|
100
|
-
"type":"email",
|
101
|
-
"data":"pizinha@yahoo.com.br",
|
102
|
-
"fid":14,
|
103
|
-
"categories":[
|
104
|
-
]
|
105
|
-
},
|
106
|
-
{
|
107
|
-
"type":"name",
|
108
|
-
"first":"Priscila",
|
109
|
-
"fid":13,
|
110
|
-
"categories":[
|
111
|
-
]
|
112
|
-
}
|
113
|
-
],
|
114
|
-
"cid":2,
|
115
|
-
"categories":[
|
116
|
-
]
|
117
|
-
}
|
76
|
+
{"fields": [{"fid": 9, "data": "carl_larsson", "type": "yahooid", "categories": []}], "type": "contact", "categories": [], "cid": 30}
|
118
77
|
]
|
119
78
|
}
|
@@ -10,16 +10,22 @@ describe Contacts::WindowsLive do
|
|
10
10
|
|
11
11
|
it 'parse the XML contacts document' do
|
12
12
|
contacts = Contacts::WindowsLive.parse_xml(contacts_xml)
|
13
|
+
contacts.size.should == 2
|
14
|
+
contacts[0].service_id == "abc"
|
15
|
+
contacts[0].name.should == "Mia Pia"
|
16
|
+
contacts[0].firstname.should == "Mia"
|
17
|
+
contacts[0].lastname.should == "Pia"
|
18
|
+
contacts[0].emails.should include("mia@hotmail.com", "othermia@yahoo.com")
|
19
|
+
contacts[0].phones.should include({"value"=>"(123) 123 1234", "type"=>"home"}, {"value"=>"(321) 555 1234", "type"=>"other"})
|
20
|
+
contacts[0].addresses.should include({"region"=>"CA", "country"=>"USA", "postalCode"=>"92123", "streetAddress"=>"123 Green St", "type"=>"home", "locality"=>"Middleville", "formatted"=>"123 Green St, Middleville, CA, 92123, USA"})
|
13
21
|
|
14
|
-
contacts[0].
|
15
|
-
contacts[
|
16
|
-
contacts[1].firstname.should ==
|
17
|
-
contacts[1].lastname.should ==
|
18
|
-
contacts[1].
|
19
|
-
contacts[1].
|
20
|
-
contacts[
|
21
|
-
contacts[2].email.should == 'betinho@hotmail.com'
|
22
|
-
|
22
|
+
contacts[0].service_id == "def"
|
23
|
+
contacts[1].name.should == ""
|
24
|
+
contacts[1].firstname.should == nil
|
25
|
+
contacts[1].lastname.should == nil
|
26
|
+
contacts[1].emails.should include("marcus@hotmail.com")
|
27
|
+
contacts[1].phones.should be_empty
|
28
|
+
contacts[1].addresses.should be_empty
|
23
29
|
end
|
24
30
|
|
25
31
|
it 'should can be initialized by a YAML file' do
|
@@ -31,6 +37,6 @@ describe Contacts::WindowsLive do
|
|
31
37
|
end
|
32
38
|
|
33
39
|
def contacts_xml
|
34
|
-
File.open(@path + '
|
40
|
+
File.open(@path + 'wl_full_contacts.xml', 'r+').read
|
35
41
|
end
|
36
42
|
end
|
data/spec/yahoo/yahoo_spec.rb
CHANGED
@@ -20,12 +20,7 @@ describe Contacts::Yahoo do
|
|
20
20
|
redirect_path = '/?appid=i%3DB%26p%3DUw70JGIdHWVRbpqYItcMw--&token=AB.KoEg8vBwvJKFkwfcDTJEMKhGeAD6KhiDe0aZLCvoJzMeQG00-&appdata=&ts=1218501215&sig=d381fba89c7e9d3c14788720733c3fbf'
|
21
21
|
|
22
22
|
results = @yahoo.contacts(redirect_path)
|
23
|
-
results.should
|
24
|
-
results.should have_contact('Nina Benchimol', 'nina@hotmail.com', 5)
|
25
|
-
results.should have_contact('Andrea Dimitri', 'and@yahoo.com',1)
|
26
|
-
results.should have_contact('Ricardo Fiorelli', 'ricardo@poli.usp.br',3)
|
27
|
-
results.should have_contact('Priscila', 'pizinha@yahoo.com.br', 2)
|
28
|
-
end
|
23
|
+
results.size.should == 3 end
|
29
24
|
|
30
25
|
it 'should validate yahoo redirect signature' do
|
31
26
|
redirect_path = '/?appid=i%3DB%26p%3DUw70JGIdHWVRbpqYItcMw--&token=AB.KoEg8vBwvJKFkwfcDTJEMKhGeAD6KhiDe0aZLCvoJzMeQG00-&appdata=&ts=1218501215&sig=d381fba89c7e9d3c14788720733c3fbf'
|
@@ -58,10 +53,14 @@ describe Contacts::Yahoo do
|
|
58
53
|
json = read_file('yh_contacts.txt')
|
59
54
|
|
60
55
|
Contacts::Yahoo.parse_contacts(json).should have_contact('Hugo Barauna', 'hugo.barauna@gmail.com', 4)
|
61
|
-
Contacts::Yahoo.parse_contacts(json).should have_contact('Nina Benchimol',
|
62
|
-
|
63
|
-
|
64
|
-
|
56
|
+
Contacts::Yahoo.parse_contacts(json).should have_contact('Nina Benchimol',
|
57
|
+
['nina@hotmail.com','nina2@yahoo.com'],
|
58
|
+
5,
|
59
|
+
[{"type" => "msn", "value" => "windowslive@msn.com"}],
|
60
|
+
[{"type" => "mobile", "value" => "808 456 7890"}],
|
61
|
+
[{"type" => "home", "value" => "123 Home Street, Super City, HI, 96815, United States"}]
|
62
|
+
)
|
63
|
+
Contacts::Yahoo.parse_contacts(json).should have_contact('carl_larsson','',30)
|
65
64
|
end
|
66
65
|
|
67
66
|
it 'should can be initialized by a YAML file' do
|
@@ -73,10 +72,19 @@ describe Contacts::Yahoo do
|
|
73
72
|
File.open(@path + file, 'r+').read
|
74
73
|
end
|
75
74
|
|
76
|
-
def have_contact(name, email, cid)
|
75
|
+
def have_contact(name, email, cid, ims = [], phones = [], addresses = [])
|
76
|
+
email = [email] if email.is_a? String
|
77
77
|
matcher_class = Class.new()
|
78
78
|
matcher_class.instance_eval do
|
79
|
-
define_method(:matches?) {|some_contacts| some_contacts.any? {|a_contact|
|
79
|
+
define_method(:matches?) {|some_contacts| some_contacts.any? {|a_contact|
|
80
|
+
a_contact.name == name && \
|
81
|
+
((a_contact.emails - email).empty?) && \
|
82
|
+
((a_contact.ims - ims).empty?) && \
|
83
|
+
((a_contact.phones - phones).empty?) && \
|
84
|
+
((a_contact.addresses - addresses).empty?) && \
|
85
|
+
a_contact.service_id == cid
|
86
|
+
}
|
87
|
+
}
|
80
88
|
end
|
81
89
|
matcher_class.new
|
82
90
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aeden-contacts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Mislav Marohni\xC6\x92\xC3\xA1"
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2009-07-
|
14
|
+
date: 2009-07-29 00:00:00 -07:00
|
15
15
|
default_executable:
|
16
16
|
dependencies: []
|
17
17
|
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- spec/feeds/google-many.xml
|
44
44
|
- spec/feeds/google-single.xml
|
45
45
|
- spec/feeds/wl_contacts.xml
|
46
|
+
- spec/feeds/wl_full_contacts.xml
|
46
47
|
- spec/feeds/yh_contacts.txt
|
47
48
|
- spec/feeds/yh_credential.xml
|
48
49
|
- spec/flickr/auth_spec.rb
|
@@ -74,6 +75,7 @@ files:
|
|
74
75
|
- vendor/windowslivelogin.rb
|
75
76
|
has_rdoc: true
|
76
77
|
homepage: http://github.com/aeden/contacts
|
78
|
+
licenses:
|
77
79
|
post_install_message:
|
78
80
|
rdoc_options:
|
79
81
|
- --charset=UTF-8
|
@@ -94,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
96
|
requirements: []
|
95
97
|
|
96
98
|
rubyforge_project:
|
97
|
-
rubygems_version: 1.
|
99
|
+
rubygems_version: 1.3.5
|
98
100
|
signing_key:
|
99
101
|
specification_version: 2
|
100
102
|
summary: Ruby library for consuming Google, Yahoo!, Flickr and Windows Live contact APIs
|