cloudsponge 0.9.13 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +19 -2
- data/README.md +13 -2
- data/cloudsponge.gemspec +4 -2
- data/lib/cloudsponge.rb +1 -0
- data/lib/cloudsponge/contact.rb +31 -51
- data/lib/cloudsponge/contact_base.rb +49 -0
- data/lib/cloudsponge/contact_importer.rb +10 -6
- data/lib/cloudsponge/utility.rb +18 -13
- data/lib/cloudsponge/version.rb +1 -1
- data/shippable.yml +16 -0
- data/test/test_contact.rb +68 -1
- data/test/test_contact_importer.rb +44 -30
- data/test/test_helper.rb +5 -4
- data/test/vcr_cassettes/aol_import.yml +245 -0
- data/test/vcr_cassettes/contacts_with_mailing_addresses.yml +8532 -0
- data/test/vcr_cassettes/u_p_import.yml +198 -0
- data/test/vcr_cassettes/wl_import.yml +636 -0
- metadata +52 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1a01d2d8ae64b616b8a026823eeef87953b9410
|
4
|
+
data.tar.gz: 4a8f24f37f4ad76c015304895e4a83a7e82480fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5023ae6e43ae5eea5d4fde43b01da0f665e72350d94f38c372535ef3e0bfa06971f04e007704308fd1b8c0c2a594148f3332d5cba3026c2a8f4bb7f855eea2f
|
7
|
+
data.tar.gz: 6b271864e6c3498ae21f51d64c3d3a65b5ff41ab4d03df03e123bb97d77a4ac967d00aaa225cabeb5cedc51c0f7a3ae1d6794d2eb66e68dca38a44402a084e41
|
data/Gemfile.lock
CHANGED
@@ -1,16 +1,33 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cloudsponge (0.
|
4
|
+
cloudsponge (0.10.0)
|
5
5
|
json (>= 1.6.1)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
|
10
|
+
addressable (2.4.0)
|
11
|
+
crack (0.4.2)
|
12
|
+
safe_yaml (~> 1.0.0)
|
13
|
+
hashdiff (0.2.3)
|
14
|
+
json (1.8.3)
|
15
|
+
rake (10.5.0)
|
16
|
+
safe_yaml (1.0.4)
|
17
|
+
vcr (3.0.0)
|
18
|
+
webmock (1.22.3)
|
19
|
+
addressable (>= 2.3.6)
|
20
|
+
crack (>= 0.3.2)
|
21
|
+
hashdiff
|
11
22
|
|
12
23
|
PLATFORMS
|
13
24
|
ruby
|
14
25
|
|
15
26
|
DEPENDENCIES
|
16
27
|
cloudsponge!
|
28
|
+
rake
|
29
|
+
vcr
|
30
|
+
webmock
|
31
|
+
|
32
|
+
BUNDLED WITH
|
33
|
+
1.11.2
|
data/README.md
CHANGED
@@ -32,6 +32,8 @@ Usage:
|
|
32
32
|
contacts = importer.get_contacts
|
33
33
|
break
|
34
34
|
end
|
35
|
+
# be nice and take a short break
|
36
|
+
sleep 1
|
35
37
|
end
|
36
38
|
```
|
37
39
|
|
@@ -47,15 +49,24 @@ Install
|
|
47
49
|
-------
|
48
50
|
|
49
51
|
```bash
|
50
|
-
|
52
|
+
gem install cloudsponge
|
51
53
|
```
|
52
54
|
|
55
|
+
OR using bunder, add
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
# cloudsponge integration library
|
59
|
+
gem 'cloudsponge', github: 'cloudsponge/cloudsponge-lib-ruby'
|
60
|
+
```
|
61
|
+
|
62
|
+
to your Gemfile
|
63
|
+
|
53
64
|
License
|
54
65
|
=======
|
55
66
|
|
56
67
|
(The MIT License)
|
57
68
|
|
58
|
-
Copyright (c)
|
69
|
+
Copyright (c) Cloud Copy, Inc.
|
59
70
|
|
60
71
|
Permission is hereby granted, free of charge, to any person obtaining
|
61
72
|
a copy of this software and associated documentation files (the
|
data/cloudsponge.gemspec
CHANGED
@@ -4,7 +4,6 @@ require File.expand_path("../lib/cloudsponge/version", __FILE__)
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "cloudsponge"
|
6
6
|
s.version = Cloudsponge::VERSION
|
7
|
-
s.licenses = ['MIT']
|
8
7
|
s.platform = Gem::Platform::RUBY
|
9
8
|
s.authors = ["Graeme Rouse"]
|
10
9
|
s.email = ["graeme@cloudsponge.com"]
|
@@ -13,7 +12,10 @@ Gem::Specification.new do |s|
|
|
13
12
|
s.description = "CloudSponge is the tool that you need to go viral. Create an account at http://www.cloudsponge.com and integrate with this library. In a few lines of code you'll have access to your users' contact lists."
|
14
13
|
|
15
14
|
s.required_rubygems_version = ">= 1.3.6"
|
16
|
-
s.
|
15
|
+
s.add_dependency "json", ">=1.6.1"
|
16
|
+
s.add_development_dependency "rake"
|
17
|
+
s.add_development_dependency "vcr"
|
18
|
+
s.add_development_dependency "webmock"
|
17
19
|
|
18
20
|
s.files = `git ls-files`.split("\n")
|
19
21
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
data/lib/cloudsponge.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/cloudsponge/version')
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/cloudsponge/contact_importer')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/cloudsponge/contact_base')
|
3
4
|
require File.expand_path(File.dirname(__FILE__) + '/cloudsponge/contact')
|
4
5
|
require File.expand_path(File.dirname(__FILE__) + '/cloudsponge/event')
|
5
6
|
require File.expand_path(File.dirname(__FILE__) + '/cloudsponge/cs_exception')
|
data/lib/cloudsponge/contact.rb
CHANGED
@@ -1,69 +1,49 @@
|
|
1
1
|
module Cloudsponge
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
class Contact < ContactBase
|
3
|
+
attribute :first_name
|
4
|
+
attribute :last_name
|
5
|
+
attribute :phones
|
6
|
+
attribute :emails
|
7
|
+
attribute :addresses
|
8
|
+
attribute :groups
|
9
|
+
attribute :dob
|
10
|
+
attribute :birthday
|
11
|
+
attribute :title
|
12
|
+
attribute :companies
|
13
|
+
attribute :job_title
|
14
|
+
attribute :photos
|
15
|
+
attribute :locations
|
16
|
+
|
10
17
|
def initialize(contact_data)
|
11
18
|
super()
|
12
|
-
|
13
|
-
self.first_name = contact_data['first_name']
|
14
|
-
self.last_name = contact_data['last_name']
|
15
|
-
|
16
|
-
# get the phone numbers
|
17
|
-
self.phones = []
|
18
|
-
contact_data['phone'] && contact_data['phone'].each do |phone|
|
19
|
-
self.add_array_value(self.phones, phone['number'], phone['type'])
|
20
|
-
end
|
21
|
-
|
22
|
-
self.emails = []
|
23
|
-
contact_data['email'] && contact_data['email'].each do |email|
|
24
|
-
self.add_array_value(self.emails, email['address'], email['type'])
|
25
|
-
end
|
26
|
-
|
27
|
-
@addresses = contact_data['address'] && contact_data['address'].inject([]) do |memo, address|
|
28
|
-
memo << {
|
29
|
-
:type => address['type'],
|
30
|
-
:street => address["street"],
|
31
|
-
:city => address["city"],
|
32
|
-
:region => address["region"],
|
33
|
-
:country => address["country"],
|
34
|
-
:postal_code => address["postal_code"],
|
35
|
-
:formatted => address["formatted"]}
|
36
|
-
end || []
|
37
|
-
|
19
|
+
@contact_data = contact_data
|
38
20
|
self
|
39
21
|
end
|
22
|
+
|
23
|
+
def self.from_array(list)
|
24
|
+
list.map { |contact_data| Contact.new(contact_data) }.compact
|
25
|
+
end
|
40
26
|
|
41
27
|
def name
|
42
28
|
"#{self.first_name} #{self.last_name}"
|
43
29
|
end
|
44
|
-
|
30
|
+
|
45
31
|
def email
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
def phone
|
50
|
-
Contact.get_first_value(self.phones)
|
32
|
+
first_from(:emails)
|
51
33
|
end
|
52
34
|
|
53
|
-
def
|
54
|
-
|
35
|
+
def phone
|
36
|
+
first_from(:phones)
|
55
37
|
end
|
56
38
|
|
57
|
-
def
|
58
|
-
|
39
|
+
def address
|
40
|
+
first_from(:addresses)
|
59
41
|
end
|
60
42
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
43
|
+
def first_from(field)
|
44
|
+
from_array = self.send(field)
|
45
|
+
return from_array && from_array.first && from_array.first[:value] unless field.to_sym == :addresses
|
46
|
+
self.addresses && self.addresses.first && "#{self.addresses.first[:street]} #{self.addresses.first[:city]} #{self.addresses.first[:region]}".strip
|
65
47
|
end
|
66
|
-
|
67
48
|
end
|
68
|
-
|
69
|
-
end
|
49
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Cloudsponge
|
2
|
+
class ContactBase
|
3
|
+
def self.attribute(name)
|
4
|
+
plural = {emails: "email", phones: "phone", addresses: "address"}
|
5
|
+
|
6
|
+
if plural.keys.include? name
|
7
|
+
define_method(name) do
|
8
|
+
send("process_#{plural[name]}", @contact_data[plural[name]])
|
9
|
+
end
|
10
|
+
else
|
11
|
+
define_method(name) do
|
12
|
+
@contact_data[name.to_s]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def process_email(content)
|
20
|
+
@emails = content && content.inject([]) do |memo, email|
|
21
|
+
email = email.inject({}){|i,(k,v)| i[k.to_sym] = v; i}
|
22
|
+
memo << {:value => email[:address], :type => email[:type]}
|
23
|
+
end || []
|
24
|
+
@emails
|
25
|
+
end
|
26
|
+
|
27
|
+
def process_phone(content)
|
28
|
+
@phones = content && content.inject([]) do |memo, phone|
|
29
|
+
phone = phone.inject({}){|i,(k,v)| i[k.to_sym] = v; i}
|
30
|
+
memo << {:value => phone[:number], :type => phone[:type]}
|
31
|
+
end || []
|
32
|
+
@phones
|
33
|
+
end
|
34
|
+
|
35
|
+
def process_address(content)
|
36
|
+
@addresses = content && content.inject([]) do |memo, address|
|
37
|
+
memo << {
|
38
|
+
:type => address['type'],
|
39
|
+
:street => address["street"],
|
40
|
+
:city => address["city"],
|
41
|
+
:region => address["region"],
|
42
|
+
:country => address["country"],
|
43
|
+
:postal_code => address["postal_code"],
|
44
|
+
:formatted => address["formatted"]}
|
45
|
+
end || []
|
46
|
+
@addresses
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -64,7 +64,7 @@ module Cloudsponge
|
|
64
64
|
full_url = generate_poll_url(EVENTS_PATH, import_id)
|
65
65
|
|
66
66
|
# get the response from the server and decode it
|
67
|
-
resp = Utility.get_and_decode_response(full_url)
|
67
|
+
resp = Utility.get_and_decode_response(full_url, auth)
|
68
68
|
# interpret the result
|
69
69
|
Event.from_array(resp['events'])
|
70
70
|
end
|
@@ -91,7 +91,7 @@ module Cloudsponge
|
|
91
91
|
|
92
92
|
# get the response from the server and decode it
|
93
93
|
begin
|
94
|
-
resp = Utility.get_and_decode_response(generate_poll_url(CONTACTS_PATH, import_id))
|
94
|
+
resp = Utility.get_and_decode_response(generate_poll_url(CONTACTS_PATH, import_id), auth)
|
95
95
|
rescue CsException => e
|
96
96
|
raise e unless e.code == 404
|
97
97
|
end
|
@@ -110,7 +110,7 @@ module Cloudsponge
|
|
110
110
|
|
111
111
|
# get and decode the response into an associated array
|
112
112
|
# Throws an exception if there was a problem at the server
|
113
|
-
Utility.post_and_decode_response(full_url(CONSENT_PATH),
|
113
|
+
Utility.post_and_decode_response(full_url(CONSENT_PATH), params, auth)
|
114
114
|
end
|
115
115
|
|
116
116
|
# invokes the begin import action for the desktop applet import process.
|
@@ -122,7 +122,7 @@ module Cloudsponge
|
|
122
122
|
|
123
123
|
# get and decode the response into an associated array
|
124
124
|
# Throws an exception if there was a problem at the server
|
125
|
-
Utility.post_and_decode_response(full_url(APPLET_PATH),
|
125
|
+
Utility.post_and_decode_response(full_url(APPLET_PATH), params, auth)
|
126
126
|
end
|
127
127
|
|
128
128
|
# invokes the begin import action for the desktop applet import process.
|
@@ -134,7 +134,7 @@ module Cloudsponge
|
|
134
134
|
|
135
135
|
# get and decode the response into an associated array
|
136
136
|
# Throws an exception if there was a problem at the server
|
137
|
-
Utility.post_and_decode_response(full_url(IMPORT_PATH),
|
137
|
+
Utility.post_and_decode_response(full_url(IMPORT_PATH), params, auth)
|
138
138
|
end
|
139
139
|
|
140
140
|
def full_url(path)
|
@@ -146,9 +146,13 @@ module Cloudsponge
|
|
146
146
|
params.merge({:domain_key => self.key, :domain_password => self.password})
|
147
147
|
end
|
148
148
|
|
149
|
+
def auth
|
150
|
+
{:domain_key => self.key, :domain_password => self.password}
|
151
|
+
end
|
152
|
+
|
149
153
|
def authenticated_query(params = {})
|
150
154
|
# append domain_key, domain_password to params and serialze into a query string
|
151
|
-
Utility.object_to_query(
|
155
|
+
Utility.object_to_query(params)
|
152
156
|
end
|
153
157
|
|
154
158
|
def create_applet_tag(id, url)
|
data/lib/cloudsponge/utility.rb
CHANGED
@@ -13,18 +13,18 @@ module Cloudsponge
|
|
13
13
|
|
14
14
|
def self.object_to_query(object)
|
15
15
|
return object unless object.is_a? Hash
|
16
|
-
object.map{ |k,v| "#{
|
16
|
+
object.map{ |k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.post_and_decode_response(url, params)
|
19
|
+
def self.post_and_decode_response(url, params, auth)
|
20
20
|
# post the response
|
21
|
-
response = post_url(url, params)
|
21
|
+
response = post_url(url, params, auth)
|
22
22
|
decode_response(response)
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.get_and_decode_response(full_url)
|
25
|
+
def self.get_and_decode_response(full_url, auth)
|
26
26
|
# get the response
|
27
|
-
response = get_url(full_url)
|
27
|
+
response = get_url(full_url, auth)
|
28
28
|
decode_response(response)
|
29
29
|
end
|
30
30
|
|
@@ -54,24 +54,29 @@ module Cloudsponge
|
|
54
54
|
object
|
55
55
|
end
|
56
56
|
|
57
|
-
def self.get_url(url)
|
57
|
+
def self.get_url(url, auth)
|
58
58
|
url = URI.parse(url)
|
59
|
-
open_http(url
|
59
|
+
open_http(url, url.query, auth, :get)
|
60
60
|
end
|
61
61
|
|
62
|
-
def self.post_url(url, params)
|
62
|
+
def self.post_url(url, params, auth)
|
63
63
|
url = URI.parse(url)
|
64
|
-
open_http(url
|
64
|
+
open_http(url, params, auth, :post)
|
65
65
|
end
|
66
66
|
|
67
|
-
def self.open_http(url)
|
67
|
+
def self.open_http(url, params, auth, method)
|
68
68
|
http = Net::HTTP.new(url.host, url.port)
|
69
|
-
# @csimport_http.read_timeout = @timeout || 30
|
70
69
|
if url.port == 443
|
71
70
|
http.use_ssl = true
|
71
|
+
end
|
72
|
+
request = if method == :post
|
73
|
+
Net::HTTP::Post.new(url.request_uri)
|
74
|
+
else
|
75
|
+
Net::HTTP::Get.new(url.request_uri)
|
72
76
|
end
|
73
|
-
|
74
|
-
|
77
|
+
request.set_form_data(params) if method == :post
|
78
|
+
request.basic_auth(auth[:domain_key], auth[:domain_password])
|
79
|
+
http.request(request)
|
75
80
|
end
|
76
81
|
end
|
77
82
|
end
|
data/lib/cloudsponge/version.rb
CHANGED
data/shippable.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.1.5
|
4
|
+
|
5
|
+
bundler_args:
|
6
|
+
--path $SHIPPABLE_BUILD_DIR/_vendor
|
7
|
+
|
8
|
+
build:
|
9
|
+
ci:
|
10
|
+
# install bundle into the cached _vendor path
|
11
|
+
- bundle install --gemfile=$SHIPPABLE_GEMFILE $SHIPPABLE_BUNDLER_ARGS
|
12
|
+
|
13
|
+
# run specs
|
14
|
+
- bundle exec rake test
|
15
|
+
|
16
|
+
cache: true
|
data/test/test_contact.rb
CHANGED
@@ -17,6 +17,73 @@ class TestContact < Test::Unit::TestCase
|
|
17
17
|
assert_equal data['last_name'], contact.last_name
|
18
18
|
assert_equal "#{data['first_name']} #{data['last_name']}", contact.name
|
19
19
|
assert_equal 'joe@example.com', contact.email
|
20
|
-
assert_equal '555-1234', contact.phone
|
20
|
+
assert_equal '555-1234' , contact.phone
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_from_all_possible_attributes
|
24
|
+
data = { "first_name" =>"Abigale Kirlin",
|
25
|
+
"last_name" =>"Kautzer",
|
26
|
+
"phone"=>
|
27
|
+
[{"number" => "1-274-714-0088", "type" => "Business fax"},
|
28
|
+
{"number" => "(719) 110-7733 x682", "type" => "Home"},
|
29
|
+
{"number" => "(425) 385-9484 x8245", "type" => "Other"},
|
30
|
+
{"number" => "906.146.3215", "type" => "Mobile"},
|
31
|
+
{"number" => "935.208.5960", "type" => "Primary"},
|
32
|
+
{"number" => "528.604.8156 x570", "type" => "Home fax"},
|
33
|
+
{"number" => "119.297.9772 x184", "type" => "Business"},
|
34
|
+
{"number" => "(712) 636-9651 x6347", "type" => "Other fax"}],
|
35
|
+
"email"=>
|
36
|
+
[{"address"=>"cesar@kub.info", "type"=>"E-mail 1"},
|
37
|
+
{"address"=>"germaine.gorczany@stroman.org", "type"=>"E-mail 2"},
|
38
|
+
{"address"=>"onie_pfannerstill@herzog.co", "type"=>"E-mail 3"}],
|
39
|
+
"address"=>
|
40
|
+
[{"type"=>"Home",
|
41
|
+
"street"=>"4535 Bednar Trace ",
|
42
|
+
"city"=>"Turnermouth",
|
43
|
+
"region"=>"Wisconsin",
|
44
|
+
"postal_code"=>"45589-5220",
|
45
|
+
"country"=>"Ghana"},
|
46
|
+
{"type"=>"Business",
|
47
|
+
"street"=>"3000 White Mill ",
|
48
|
+
"city"=>"Dachburgh",
|
49
|
+
"region"=>"South Dakota",
|
50
|
+
"postal_code"=>"38529-1507",
|
51
|
+
"country"=>"Sweden"},
|
52
|
+
{"type"=>"Other",
|
53
|
+
"street"=>"5997 Wolf Underpass ",
|
54
|
+
"city"=>"Port Tyrese",
|
55
|
+
"region"=>"Colorado",
|
56
|
+
"postal_code"=>"32992-0271",
|
57
|
+
"country"=>"Tanzania"}],
|
58
|
+
"groups"=>[],
|
59
|
+
"dob"=>"1994-08-27",
|
60
|
+
"birthday"=>"08-27",
|
61
|
+
"companies"=>["O'Conner Inc"],
|
62
|
+
"title"=> "Mr.",
|
63
|
+
"job_title"=>"District Integration Administrator",
|
64
|
+
"photos"=>[],
|
65
|
+
"locations"=>[]}
|
66
|
+
|
67
|
+
assert contact = Cloudsponge::Contact.new(data)
|
68
|
+
assert_equal data['first_name'], contact.first_name
|
69
|
+
assert_equal data['last_name'], contact.last_name
|
70
|
+
assert_equal "#{data['first_name']} #{data['last_name']}", contact.name
|
71
|
+
|
72
|
+
assert_equal 'cesar@kub.info', contact.email
|
73
|
+
assert_equal '1-274-714-0088', contact.phone
|
74
|
+
assert_equal '4535 Bednar Trace Turnermouth Wisconsin', contact.address
|
75
|
+
|
76
|
+
assert_equal Array, contact.emails.class
|
77
|
+
assert_equal Array, contact.phones.class
|
78
|
+
assert_equal Array, contact.addresses.class
|
79
|
+
|
80
|
+
assert_equal data["groups"] , contact.groups
|
81
|
+
assert_equal data["dob"] , contact.dob
|
82
|
+
assert_equal data["birthday"] , contact.birthday
|
83
|
+
assert_equal data["companies"], contact.companies
|
84
|
+
assert_equal data["title"] , contact.title
|
85
|
+
assert_equal data["job_title"], contact.job_title
|
86
|
+
assert_equal data["photos"] , contact.photos
|
87
|
+
assert_equal data["locations"], contact.locations
|
21
88
|
end
|
22
89
|
end
|