fullcontacter 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|