cloudsponge 0.9.13 → 0.10.0
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.
- 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
|