fullcontacter 0.3.2
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/.document +5 -0
- data/.gitignore +53 -0
- data/.rspec +3 -0
- data/Gemfile +3 -0
- data/LICENSE.md +20 -0
- data/README.md +36 -0
- data/Rakefile +25 -0
- data/VERSION +1 -0
- data/bugs.txt +2 -0
- data/fullcontact.gemspec +34 -0
- data/lib/faraday/request/gateway.rb +18 -0
- data/lib/faraday/response/fullcontact_errors.rb +33 -0
- data/lib/faraday/response/raise_http_4xx.rb +45 -0
- data/lib/faraday/response/raise_http_5xx.rb +24 -0
- data/lib/fullcontact.rb +27 -0
- data/lib/fullcontact/api.rb +21 -0
- data/lib/fullcontact/client.rb +32 -0
- data/lib/fullcontact/client/batch_process.rb +35 -0
- data/lib/fullcontact/client/contact.rb +119 -0
- data/lib/fullcontact/client/contact_list.rb +84 -0
- data/lib/fullcontact/client/icon.rb +35 -0
- data/lib/fullcontact/client/name.rb +167 -0
- data/lib/fullcontact/client/person.rb +94 -0
- data/lib/fullcontact/client/provisioning.rb +28 -0
- data/lib/fullcontact/client/snapshot.rb +31 -0
- data/lib/fullcontact/client/subscription.rb +45 -0
- data/lib/fullcontact/client/user.rb +28 -0
- data/lib/fullcontact/configuration.rb +95 -0
- data/lib/fullcontact/connection.rb +36 -0
- data/lib/fullcontact/error.rb +35 -0
- data/lib/fullcontact/request.rb +43 -0
- data/lib/fullcontact/version.rb +3 -0
- data/spec/faraday/response_spec.rb +56 -0
- data/spec/fixtures/clear_contact_list.json +3 -0
- data/spec/fixtures/contact_history.json +16 -0
- data/spec/fixtures/create_contact_list.json +4 -0
- data/spec/fixtures/create_snapshot.json +7 -0
- data/spec/fixtures/create_subscription.json +4 -0
- data/spec/fixtures/deduce_by_email.json +13 -0
- data/spec/fixtures/deduce_by_username.json +13 -0
- data/spec/fixtures/delete_contact.json +4 -0
- data/spec/fixtures/delete_contact_list.json +3 -0
- data/spec/fixtures/delete_subscription.json +3 -0
- data/spec/fixtures/get_contact.json +20 -0
- data/spec/fixtures/get_contact_lists.json +11 -0
- data/spec/fixtures/get_contacts_in_a_list.json +41 -0
- data/spec/fixtures/get_enriched_contact.json +261 -0
- data/spec/fixtures/get_updates.json +252 -0
- data/spec/fixtures/has_enriched_updates.json +4 -0
- data/spec/fixtures/list_snapshots.json +7 -0
- data/spec/fixtures/list_subscriptions.json +10 -0
- data/spec/fixtures/normalize.json +27 -0
- data/spec/fixtures/parse.json +10 -0
- data/spec/fixtures/person.json +47 -0
- data/spec/fixtures/queue_contact_list_for_enrichment.json +3 -0
- data/spec/fixtures/save_enriched_contact.json +261 -0
- data/spec/fixtures/similarity.json +45 -0
- data/spec/fixtures/stats_by_family_name.json +12 -0
- data/spec/fixtures/stats_by_given_and_family_name.json +62 -0
- data/spec/fixtures/stats_by_given_name.json +57 -0
- data/spec/fixtures/stats_by_name.json +64 -0
- data/spec/fixtures/update_contact.json +9 -0
- data/spec/fullcontact/api_spec.rb +68 -0
- data/spec/fullcontact/client/contact_list_spec.rb +89 -0
- data/spec/fullcontact/client/contact_spec.rb +108 -0
- data/spec/fullcontact/client/icon_spec.rb +24 -0
- data/spec/fullcontact/client/name_spec.rb +121 -0
- data/spec/fullcontact/client/person_spec.rb +77 -0
- data/spec/fullcontact/client/snapshot_spec.rb +35 -0
- data/spec/fullcontact/client/subscription_spec.rb +47 -0
- data/spec/fullcontact/client_spec.rb +10 -0
- data/spec/fullcontact_spec.rb +114 -0
- data/spec/helper.rb +39 -0
- metadata +384 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module FullContact
|
2
|
+
class Client
|
3
|
+
module Provisioning
|
4
|
+
# Public:The Provisioning method creates a new API key based on an
|
5
|
+
# Account Key. This method is useful when your application has many end
|
6
|
+
# users that you would like to track separately. An account key is
|
7
|
+
# required for accessing this api method. This account key can be
|
8
|
+
# initialized through the configure method. For getting an account key,
|
9
|
+
# send an email to support@fullcontact.com.
|
10
|
+
#
|
11
|
+
# Example
|
12
|
+
#
|
13
|
+
# api_key = FullContact.create_new_api_key
|
14
|
+
#
|
15
|
+
# Returns a hash which contains the generated api_key and monthly quota
|
16
|
+
def create_new_api_key
|
17
|
+
# return error if no provisioning key defined
|
18
|
+
return unless FullContact.options[:account_key]
|
19
|
+
self.endpoint = 'https://api.fullcontact.com/apiKey'
|
20
|
+
options = {:accountKey => FullContact.options[:account_key]}
|
21
|
+
get('new', options)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module FullContact
|
2
|
+
class Client
|
3
|
+
module Snapshot
|
4
|
+
# Public: Creates a snapshot in order to store a point-in-time backup of a contactList
|
5
|
+
#
|
6
|
+
# list_id - id of the contact list to be backed-up
|
7
|
+
# options - hash containing additonal arguments
|
8
|
+
# :name - Name of the snapshot
|
9
|
+
#
|
10
|
+
# Example
|
11
|
+
#
|
12
|
+
# response = FullContact.create_snapshot(list_id, {:name => 'foo'})
|
13
|
+
# response.result now contains the snapshot name and timestamp
|
14
|
+
def create_snapshot(list_id, options)
|
15
|
+
post("contactList/#{list_id}/snapshot", options)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Public: List all snapshots associated with a contact list
|
19
|
+
#
|
20
|
+
# list_id - id of the contact list for which snapshots need to be fetched
|
21
|
+
#
|
22
|
+
# Example
|
23
|
+
#
|
24
|
+
# response = FullContact.list_snapshots(list_id)
|
25
|
+
# response.snapshots gives a list of snapshot names
|
26
|
+
def list_snapshots(list_id)
|
27
|
+
get("contactList/#{list_id}/snapshot")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module FullContact
|
2
|
+
class Client
|
3
|
+
module Subscription
|
4
|
+
# Public: Creates a subscription to a contactList in order to receive webhook notifications for certain events
|
5
|
+
#
|
6
|
+
# list_id - id of the contact list for which subscription is to be created
|
7
|
+
# options - hash containing additional arguments
|
8
|
+
# :event Type of event. Only 'enriched' is supported right now
|
9
|
+
# :callback Callback URL to post to when event occurs
|
10
|
+
#
|
11
|
+
# Example
|
12
|
+
#
|
13
|
+
# response = FullContact.create_subscription(list_id, {:event => 'enriched', :callback => callback_url })
|
14
|
+
# response.id contains the subscription id
|
15
|
+
def create_subscription(list_id, options)
|
16
|
+
post("contactList/#{list_id}/subscribe", options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Public: Lists all subscriptions associated with a contactList
|
20
|
+
#
|
21
|
+
# list_id - id of the contact list for which subscription is to be created
|
22
|
+
#
|
23
|
+
# Example
|
24
|
+
#
|
25
|
+
# response = FullContact.list_subscriptions(list_id)
|
26
|
+
# response.subscriptions contains list of all subscriptions for this contact list
|
27
|
+
def list_subscriptions(list_id)
|
28
|
+
get("contactList/#{list_id}/subscribe")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Public: Delete a subscription associated with a contactList
|
32
|
+
#
|
33
|
+
# list_id - id of the contact list for which subscription is to be created
|
34
|
+
# options - hash containing additional arguments
|
35
|
+
# :subscription id of the subscription to delete
|
36
|
+
#
|
37
|
+
# Example
|
38
|
+
#
|
39
|
+
# response = FullContact.delete_subscriptions(list_id, {:subscription => subscription_id})
|
40
|
+
def delete_subscription(list_id, options)
|
41
|
+
delete("contactList/#{list_id}/subscribe", options)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module FullContact
|
2
|
+
class Client
|
3
|
+
module User
|
4
|
+
# Public: Authenticate a user using the username and password. If
|
5
|
+
# authenticated, sets the returned access_token in a access_token config
|
6
|
+
# variable
|
7
|
+
#
|
8
|
+
# options - a hash containing the user's username and password
|
9
|
+
#
|
10
|
+
# Example
|
11
|
+
#
|
12
|
+
# FullContact.authenticate({ :username => 'prafullakiran@gmail.com',
|
13
|
+
# :password => 'grizzlybear' })
|
14
|
+
# # we're authenticated now
|
15
|
+
# contact_lists = FullContact.get_contact_lists
|
16
|
+
def authenticate(options = {})
|
17
|
+
self.endpoint = 'https://api.fullcontact.com/auth/'
|
18
|
+
self.format = ''
|
19
|
+
access_token = post('token', options)
|
20
|
+
|
21
|
+
FullContact.configure do |config|
|
22
|
+
config.access_token = access_token
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module FullContact
|
4
|
+
# Defines constants and methods related to configuration
|
5
|
+
module Configuration
|
6
|
+
# An array of valid keys in the options hash when configuring a {FullContact::API}
|
7
|
+
VALID_OPTIONS_KEYS = [
|
8
|
+
:adapter,
|
9
|
+
:api_key,
|
10
|
+
:account_key,
|
11
|
+
:get_request_url_only,
|
12
|
+
:endpoint,
|
13
|
+
:format,
|
14
|
+
:access_token,
|
15
|
+
:gateway,
|
16
|
+
:proxy,
|
17
|
+
:user_agent].freeze
|
18
|
+
|
19
|
+
# An array of valid request/response formats
|
20
|
+
#
|
21
|
+
# @note Not all methods support the XML format.
|
22
|
+
VALID_FORMATS = [
|
23
|
+
:json,
|
24
|
+
:xml].freeze
|
25
|
+
|
26
|
+
# The adapter that will be used to connect if none is set
|
27
|
+
#
|
28
|
+
# @note The default faraday adapter is Net::HTTP.
|
29
|
+
DEFAULT_ADAPTER = Faraday.default_adapter
|
30
|
+
|
31
|
+
# By default, don't set an api key
|
32
|
+
DEFAULT_API_KEY = nil
|
33
|
+
|
34
|
+
# By default, don't set an access key
|
35
|
+
DEFAULT_ACCESS_TOKEN = nil
|
36
|
+
|
37
|
+
# By default, don't set an account key
|
38
|
+
DEFAULT_ACCOUNT_KEY = nil
|
39
|
+
|
40
|
+
# By default, get full response
|
41
|
+
GET_REQUEST_URL_ONLY = false
|
42
|
+
|
43
|
+
# The endpoint that will be used to connect if none is set
|
44
|
+
#
|
45
|
+
DEFAULT_ENDPOINT = 'https://api.fullcontact.com/v2/'.freeze
|
46
|
+
|
47
|
+
# The response format appended to the path and sent in the 'Accept' header if none is set
|
48
|
+
#
|
49
|
+
# @note JSON is preferred over XML because it is more concise and faster to parse.
|
50
|
+
DEFAULT_FORMAT = :json
|
51
|
+
|
52
|
+
# By default, don't use a proxy server
|
53
|
+
DEFAULT_PROXY = nil
|
54
|
+
|
55
|
+
# The user agent that will be sent to the API endpoint if none is set
|
56
|
+
DEFAULT_USER_AGENT = "FullContact Ruby Gem".freeze
|
57
|
+
|
58
|
+
DEFAULT_GATEWAY = nil
|
59
|
+
|
60
|
+
# @private
|
61
|
+
attr_accessor *VALID_OPTIONS_KEYS
|
62
|
+
|
63
|
+
# When this module is extended, set all configuration options to their default values
|
64
|
+
def self.extended(base)
|
65
|
+
base.reset
|
66
|
+
end
|
67
|
+
|
68
|
+
# Convenience method to allow configuration options to be set in a block
|
69
|
+
def configure
|
70
|
+
yield self
|
71
|
+
end
|
72
|
+
|
73
|
+
# Create a hash of options and their values
|
74
|
+
def options
|
75
|
+
options = {}
|
76
|
+
VALID_OPTIONS_KEYS.each{|k| options[k] = send(k) }
|
77
|
+
options
|
78
|
+
end
|
79
|
+
|
80
|
+
# Reset all configuration options to defaults
|
81
|
+
def reset
|
82
|
+
self.adapter = DEFAULT_ADAPTER
|
83
|
+
self.api_key = DEFAULT_API_KEY
|
84
|
+
self.access_token = DEFAULT_ACCESS_TOKEN
|
85
|
+
self.account_key = DEFAULT_ACCOUNT_KEY
|
86
|
+
self.get_request_url_only = GET_REQUEST_URL_ONLY
|
87
|
+
self.endpoint = DEFAULT_ENDPOINT
|
88
|
+
self.format = DEFAULT_FORMAT
|
89
|
+
self.proxy = DEFAULT_PROXY
|
90
|
+
self.user_agent = DEFAULT_USER_AGENT
|
91
|
+
self.gateway = DEFAULT_GATEWAY
|
92
|
+
self
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'faraday_middleware'
|
2
|
+
require 'faraday/request/gateway'
|
3
|
+
require 'faraday/response/fullcontact_errors'
|
4
|
+
|
5
|
+
|
6
|
+
module FullContact
|
7
|
+
# @private
|
8
|
+
module Connection
|
9
|
+
private
|
10
|
+
|
11
|
+
def connection(raw=false)
|
12
|
+
options = {
|
13
|
+
:headers => {'Accept' => "application/#{format}", 'User-Agent' => user_agent},
|
14
|
+
:proxy => proxy,
|
15
|
+
:ssl => {:verify => false},
|
16
|
+
:url => api_endpoint,
|
17
|
+
}
|
18
|
+
|
19
|
+
Faraday.new(options) do |builder|
|
20
|
+
builder.use Faraday::Request::UrlEncoded
|
21
|
+
builder.use Faraday::Request::Gateway, gateway if gateway
|
22
|
+
builder.use Faraday::Response::Rashify unless raw
|
23
|
+
unless raw
|
24
|
+
case format.to_s.downcase
|
25
|
+
when 'json'
|
26
|
+
builder.use Faraday::Response::ParseJson
|
27
|
+
when 'xml'
|
28
|
+
builder.use Faraday::Response::ParseXml
|
29
|
+
end
|
30
|
+
end
|
31
|
+
builder.use Faraday::Response::FullContactErrors
|
32
|
+
builder.adapter Faraday.default_adapter
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module FullContact
|
2
|
+
# Custom error class for rescuing from all FullContact errors
|
3
|
+
class Error < StandardError
|
4
|
+
attr_reader :http_headers
|
5
|
+
|
6
|
+
def initialize(message, http_headers)
|
7
|
+
@http_headers = Hash[http_headers]
|
8
|
+
super message
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Raised when FullContact returns the HTTP status code 400
|
13
|
+
class BadRequest < Error; end
|
14
|
+
|
15
|
+
# Raised when FullContact returns the HTTP status code 401
|
16
|
+
class Unauthorized < Error; end
|
17
|
+
|
18
|
+
# Raised when FullContact returns the HTTP status code 403
|
19
|
+
class Forbidden < Error; end
|
20
|
+
|
21
|
+
# Raised when FullContact returns the HTTP status code 404
|
22
|
+
class NotFound < Error; end
|
23
|
+
|
24
|
+
# Raised when FullContact returns the HTTP status code 422
|
25
|
+
class Invalid < Error; end
|
26
|
+
|
27
|
+
# Raised when FullContact returns the HTTP status code 500
|
28
|
+
class InternalServerError < Error; end
|
29
|
+
|
30
|
+
# Raised when FullContact returns the HTTP status code 502
|
31
|
+
class BadGateway < Error; end
|
32
|
+
|
33
|
+
# Raised when FullContact returns the HTTP status code 503
|
34
|
+
class ServiceUnavailable < Error; end
|
35
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module FullContact
|
2
|
+
# Defines HTTP request methods
|
3
|
+
module Request
|
4
|
+
# Perform an HTTP GET request
|
5
|
+
def get(path, options={}, raw=false)
|
6
|
+
request(:get, path, options, raw)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Perform an HTTP POST request
|
10
|
+
def post(path, options={}, raw=false)
|
11
|
+
request(:post, path, options, raw)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Perform an HTTP DELETE request
|
15
|
+
def delete(path, options={}, raw=false)
|
16
|
+
request(:delete, path, options, raw)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Perform an HTTP request
|
22
|
+
def request(method, path, options, raw=false)
|
23
|
+
if FullContact.options[:get_request_url_only]
|
24
|
+
return connection(raw).build_url(formatted_path(path), options)
|
25
|
+
end
|
26
|
+
options[:apiKey] = FullContact.options[:api_key]
|
27
|
+
unless FullContact.options[:access_token].nil?
|
28
|
+
options[:accessToken] = FullContact.options[:access_token]
|
29
|
+
end
|
30
|
+
response = connection(raw).send(method) do |request|
|
31
|
+
request.url(formatted_path(path), options)
|
32
|
+
request.headers["Content-Type"] = options[:content_type] if options.include?(:content_type)
|
33
|
+
request.body = options[:request_body] if options.include?(:request_body)
|
34
|
+
end
|
35
|
+
raw ? response : response.body
|
36
|
+
end
|
37
|
+
|
38
|
+
def formatted_path(path)
|
39
|
+
return path if format.to_s.empty?
|
40
|
+
[path, format].compact.join('.')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'faraday'
|
3
|
+
require 'fullcontact'
|
4
|
+
|
5
|
+
describe Faraday::Response do
|
6
|
+
before do
|
7
|
+
FullContact.configure do |config|
|
8
|
+
config.api_key = "api_key"
|
9
|
+
end
|
10
|
+
@client = FullContact::Client.new
|
11
|
+
end
|
12
|
+
|
13
|
+
{
|
14
|
+
400 => FullContact::BadRequest,
|
15
|
+
401 => FullContact::Unauthorized,
|
16
|
+
403 => FullContact::Forbidden,
|
17
|
+
404 => FullContact::NotFound,
|
18
|
+
422 => FullContact::Invalid,
|
19
|
+
500 => FullContact::InternalServerError,
|
20
|
+
502 => FullContact::BadGateway,
|
21
|
+
503 => FullContact::ServiceUnavailable,
|
22
|
+
}.each do |status, exception|
|
23
|
+
if (status >= 500)
|
24
|
+
context "when HTTP status is #{status}" do
|
25
|
+
before do
|
26
|
+
stub_get('person.json').
|
27
|
+
with(:query => {:apiKey => "api_key", :email => 'brawest@gmail.com'}).
|
28
|
+
to_return(:status => status)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should raise #{exception.name} error" do
|
32
|
+
lambda do
|
33
|
+
@client.lookup_by_email('brawest@gmail.com')
|
34
|
+
end.should raise_error(exception)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
else
|
38
|
+
[nil, "error", "errors"].each do |body|
|
39
|
+
context "when HTTP status is #{status} and body is #{body||='nil'}" do
|
40
|
+
before do
|
41
|
+
body_message = '{"'+body+'":"test"}' unless body.nil?
|
42
|
+
stub_get('person.json').
|
43
|
+
with(:query => {:apiKey => "api_key", :email => 'brawest@gmail.com'}).
|
44
|
+
to_return(:status => status, :body => body_message)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should raise #{exception.name} error" do
|
48
|
+
lambda do
|
49
|
+
@client.lookup_by_email('brawest@gmail.com')
|
50
|
+
end.should raise_error(exception)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"history":
|
3
|
+
[
|
4
|
+
{
|
5
|
+
"eTag": "fffffec9b5094cf18aaef4da318436755124a12d2422eaf2c9c44b95",
|
6
|
+
"date": "2012-03-25T17:45:43.441Z",
|
7
|
+
"action": "Enriched"
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"eTag": "fffffec9b536c589363364e51a5dc9800f54d11cdbf1a21fe94ef35b",
|
11
|
+
"date": "2012-03-25T16:56:03.448Z",
|
12
|
+
"action": "Added"
|
13
|
+
}
|
14
|
+
],
|
15
|
+
"status": 200
|
16
|
+
}
|