netprospex-ruby 0.0.3

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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +4 -0
  7. data/fixtures/cassettes/acl-error.yml +45 -0
  8. data/fixtures/cassettes/auth-error.yml +45 -0
  9. data/fixtures/cassettes/incomplete-organization.yml +55 -0
  10. data/fixtures/cassettes/incomplete-person.yml +52 -0
  11. data/fixtures/cassettes/industries.yml +136 -0
  12. data/fixtures/cassettes/pag-error.yml +45 -0
  13. data/fixtures/cassettes/person-by-email.yml +55 -0
  14. data/fixtures/cassettes/person-by-id.yml +55 -0
  15. data/fixtures/cassettes/person-list.yml +619 -0
  16. data/fixtures/cassettes/req-error.yml +45 -0
  17. data/lib/netprospex.rb +8 -0
  18. data/lib/netprospex/api/address.rb +9 -0
  19. data/lib/netprospex/api/organization.rb +10 -0
  20. data/lib/netprospex/api/person.rb +10 -0
  21. data/lib/netprospex/api/phone.rb +9 -0
  22. data/lib/netprospex/api/sub_objects.rb +52 -0
  23. data/lib/netprospex/client.rb +53 -0
  24. data/lib/netprospex/configuration.rb +28 -0
  25. data/lib/netprospex/exceptions.rb +13 -0
  26. data/lib/netprospex/helpers/formatters.rb +67 -0
  27. data/lib/netprospex/middleware/raise_exceptions.rb +34 -0
  28. data/lib/netprospex/middleware/rubyize.rb +16 -0
  29. data/lib/netprospex/query_methods.rb +41 -0
  30. data/lib/netprospex/version.rb +3 -0
  31. data/netprospex.gemspec +31 -0
  32. data/spec/netprospex/api/organization_spec.rb +51 -0
  33. data/spec/netprospex/api/person_spec.rb +45 -0
  34. data/spec/netprospex/client_spec.rb +34 -0
  35. data/spec/netprospex/configuration_spec.rb +21 -0
  36. data/spec/netprospex/helpers/formatters_spec.rb +78 -0
  37. data/spec/netprospex/middleware/raise_exceptions_spec.rb +92 -0
  38. data/spec/netprospex/query_methods_spec.rb +68 -0
  39. data/spec/netprospex_spec.rb +5 -0
  40. data/spec/spec_helper.rb +7 -0
  41. data/spec/vcr_helper.rb +12 -0
  42. metadata +236 -0
@@ -0,0 +1,45 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://api.netprospex.com/1.1/person/list.json
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.8.7
12
+ Authorization:
13
+ - OAuth oauth_consumer_key="<NETPROSPEX_KEY>", oauth_nonce="2e2556d88815db3044d263110492c76d",
14
+ oauth_signature="MX5V81z3L50m1oIYkNYYn%2BgLT18%3D", oauth_signature_method="HMAC-SHA1",
15
+ oauth_timestamp="1366302031", oauth_token="<NETPROSPEX_USER_TOKEN>", oauth_version="1.0"
16
+ Accept-Encoding:
17
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
18
+ Accept:
19
+ - ! '*/*'
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Date:
26
+ - Thu, 18 Apr 2013 16:20:32 GMT
27
+ Server:
28
+ - Apache/2.2.22 (Unix) mod_ssl/2.2.22 OpenSSL/1.0.0-fips DAV/2 mod_wsgi/3.3
29
+ Python/2.7.2 PHP/5.3.10
30
+ X-Powered-By:
31
+ - PHP/5.3.10
32
+ Connection:
33
+ - close
34
+ Content-Length:
35
+ - '484'
36
+ Content-Type:
37
+ - application/json
38
+ body:
39
+ encoding: US-ASCII
40
+ string: ! '{"response":{"version":"1.1","responseId":"CB93209F-A577-A249-8714-7849B42E325F","responseType":"error","request":{"startTime":"2013-04-18
41
+ 12:20:32","requestType":"person_list","url":"\/1.1\/person\/list.json","userId":"d5c72b79-a2ed-11e2-8c42-00259059ba92"},"transaction":{"accountId":"d5c51e5f-a2ed-11e2-8c42-00259059ba92","accountStartBalance":7120,"accountEndBalance":null},"error":{"message":"no
42
+ valid arguments were found","code":"REQ"},"debug":{"requestTime":0.0180189609528}}}'
43
+ http_version:
44
+ recorded_at: Thu, 18 Apr 2013 16:20:32 GMT
45
+ recorded_with: VCR 2.4.0
data/lib/netprospex.rb ADDED
@@ -0,0 +1,8 @@
1
+ Dir[File.dirname(__FILE__) + '/netprospex/helpers/*.rb'].each {|file| require file }
2
+ Dir[File.dirname(__FILE__) + '/netprospex/middleware/*.rb'].each {|file| require file }
3
+ Dir[File.dirname(__FILE__) + '/netprospex/api/*.rb'].each {|file| require file }
4
+ Dir[File.dirname(__FILE__) + '/netprospex/*.rb'].each {|file| require file }
5
+
6
+ module NetProspex
7
+ extend Configuration
8
+ end
@@ -0,0 +1,9 @@
1
+ require 'ostruct'
2
+
3
+ module NetProspex::Api
4
+ class Address < OpenStruct
5
+ def to_s
6
+ self.formatted_address
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'netprospex/api/sub_objects.rb'
2
+ require 'ostruct'
3
+
4
+ module NetProspex::Api
5
+ class Organization < OpenStruct
6
+ include HasAddress
7
+ include HasPhones
8
+ include HasDomains
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'netprospex/api/sub_objects.rb'
2
+ require 'ostruct'
3
+
4
+ module NetProspex::Api
5
+ class Person < OpenStruct
6
+ include HasAddress
7
+ include HasPhones
8
+ include HasOrganization
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ require 'ostruct'
2
+
3
+ module NetProspex::Api
4
+ class Phone < OpenStruct
5
+ def to_s
6
+ self.formatted_number
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,52 @@
1
+ module NetProspex::Api
2
+ module HasPhones
3
+ def initialize(*args)
4
+ super(*args)
5
+ self.phones ||= []
6
+ self.phones.map! do |phone|
7
+ if phone.is_a? Hash
8
+ if phone[:national_number] && !phone[:national_number].empty?
9
+ NetProspex::Api::Phone.new(phone)
10
+ else
11
+ nil
12
+ end
13
+ else
14
+ phone
15
+ end
16
+ end
17
+ self.phones.compact!
18
+ end
19
+ end
20
+ module HasAddress
21
+ def initialize(*args)
22
+ super(*args)
23
+ if self.postal_address.is_a? Hash
24
+ formatted_address = self.postal_address[:formatted_address]
25
+ if formatted_address && !formatted_address.empty?
26
+ self.postal_address = NetProspex::Api::Address.new(self.postal_address)
27
+ else
28
+ self.postal_address = nil
29
+ end
30
+ end
31
+ end
32
+ end
33
+ module HasOrganization
34
+ def initialize(*args)
35
+ super(*args)
36
+ if self.organization.is_a? Hash
37
+ self.organization = NetProspex::Api::Organization.new(self.organization)
38
+ end
39
+ end
40
+ end
41
+ module HasDomains
42
+ def initialize(*args)
43
+ super(*args)
44
+ if self.domains.is_a? Hash
45
+ domain = self.domains.fetch(:domain, {})[:url]
46
+ self.domains = domain ? [domain] : []
47
+ elsif self.domains.is_a? Array #TODO: I'm just guessing at this formatting
48
+ self.domains.map! {|h| h[:domain][:url]}
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,53 @@
1
+ require "netprospex/query_methods"
2
+ require "faraday"
3
+ require "faraday_middleware"
4
+
5
+ module NetProspex
6
+ class Client
7
+ include NetProspex::Helpers::Formatters
8
+ include NetProspex::QueryMethods
9
+ attr_reader :account_balance
10
+
11
+ def initialize(token, secret)
12
+ @token = token
13
+ @secret = secret
14
+ end
15
+
16
+ def get(path, query={})
17
+ http.get(api_url(path, query)).body
18
+ end
19
+
20
+ def post(path, params={})
21
+ http.post(api_url(path), params).body
22
+ end
23
+
24
+ protected
25
+
26
+ def api_base
27
+ @api_base = "#{NetProspex.scheme}://api.netprospex.com/#{NetProspex.version}"
28
+ end
29
+
30
+ def api_url(path, query={})
31
+ api_base + path + stringify_query(query)
32
+ end
33
+
34
+ def http
35
+ raise NetProspex::ConfigurationError if api_base.nil?
36
+
37
+ @http ||= Faraday.new do |builder|
38
+ builder.use Faraday::Request::OAuth, {
39
+ consumer_key: NetProspex.consumer_key,
40
+ consumer_secret: NetProspex.consumer_secret,
41
+ token: @token,
42
+ token_secret: @secret
43
+ }
44
+
45
+ builder.use NetProspex::Middleware::RaiseExceptions
46
+ builder.use NetProspex::Middleware::Rubyize, content_type: /\bjson$/
47
+ builder.use FaradayMiddleware::ParseJson, content_type: /\bjson$/
48
+
49
+ builder.adapter :net_http
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,28 @@
1
+ module NetProspex
2
+ module Configuration
3
+ attr_accessor :consumer_key, :consumer_secret, :scheme
4
+ attr_reader :version
5
+
6
+ def version=(v)
7
+ @version = v
8
+ end
9
+
10
+ def scheme
11
+ @scheme || 'http'
12
+ end
13
+
14
+ def self.extended(base)
15
+ base.reset
16
+ end
17
+
18
+ def reset
19
+ self.consumer_key = nil
20
+ self.consumer_secret = nil
21
+ self.version = "1.1"
22
+ end
23
+
24
+ def configure
25
+ yield self
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module NetProspex
2
+ class Error < StandardError; end
3
+ class ConfigurationError < Error; end
4
+
5
+ class ApiError < Error; end
6
+ class AccessDenied < ApiError; end
7
+ class AuthenticationError < ApiError; end
8
+ class DatabaseError < ApiError; end
9
+ class SearchError < ApiError; end
10
+ class PaginationError < ApiError; end
11
+ class ArgumentMissing < ApiError; end
12
+ class ZeroBalanceError < ApiError; end
13
+ end
@@ -0,0 +1,67 @@
1
+ require "active_support/all"
2
+ require "uri"
3
+
4
+ module NetProspex
5
+ module Helpers
6
+ module Formatters
7
+ def stringify_query(query)
8
+ return "" if query.blank?
9
+ components = []
10
+ unrubyize_keys(query).each do |k,v|
11
+ if v.is_a? Array
12
+ v.each do |w|
13
+ components << [k+'[]', w]
14
+ end
15
+ else
16
+ components << [k,v]
17
+ end
18
+ end
19
+ "?" + URI.encode_www_form(components)
20
+ end
21
+
22
+ def unrubyize_keys(hash)
23
+ new_hash = {}
24
+ hash.each do |k,v|
25
+ new_k = case k
26
+ when Symbol
27
+ k.to_s.camelize(:lower)
28
+ else
29
+ k
30
+ end
31
+ new_v = case v
32
+ when Hash
33
+ unrubyize_keys(v)
34
+ when Array
35
+ v.map {|w| (Hash === w) ? unrubyize_keys(w) : w}
36
+ else
37
+ v
38
+ end
39
+ new_hash[new_k] = new_v
40
+ end
41
+ new_hash
42
+ end
43
+
44
+ def rubyize_keys(hash)
45
+ new_hash = {}
46
+ hash.each do |k,v|
47
+ new_k = case k
48
+ when String
49
+ k.underscore.to_sym
50
+ else
51
+ k
52
+ end
53
+ new_v = case v
54
+ when Hash
55
+ rubyize_keys(v)
56
+ when Array
57
+ v.map {|w| (Hash === w) ? rubyize_keys(w) : w}
58
+ else
59
+ v
60
+ end
61
+ new_hash[new_k] = new_v
62
+ end
63
+ new_hash
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,34 @@
1
+ require 'faraday_middleware/response_middleware'
2
+
3
+ module NetProspex
4
+ module Middleware
5
+ class RaiseExceptions < Faraday::Middleware
6
+ def call(environment)
7
+ @app.call(environment).on_complete do |env|
8
+ next unless env[:body].is_a?(Hash) && env[:body][:response][:error]
9
+ error = env[:body][:response][:error]
10
+ case error[:code]
11
+ when "ACL"
12
+ raise NetProspex::AccessDenied.new(error[:message])
13
+ when "AUTH"
14
+ raise NetProspex::AuthenticationError.new(error[:message])
15
+ when "DB"
16
+ raise NetProspex::DatabaseError.new(error[:message])
17
+ when "SS"
18
+ raise NetProspex::SearchError.new(error[:message])
19
+ when "PAG"
20
+ raise NetProspex::PaginationError.new(error[:message])
21
+ when "REQ"
22
+ raise NetProspex::ArgumentMissing.new(error[:message])
23
+ when "ZBAL"
24
+ raise NetProspex::ZeroBalanceError.new(error[:message])
25
+ when "FAULT","UNX"
26
+ raise NetProspex::ApiError.new(error[:message])
27
+ else
28
+ raise NetProspex::ApiError.new(error[:message])
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,16 @@
1
+ require 'faraday_middleware/response_middleware'
2
+ module NetProspex
3
+ module Middleware
4
+ class Rubyize < FaradayMiddleware::ResponseMiddleware
5
+ extend NetProspex::Helpers::Formatters
6
+
7
+ define_parser do |body|
8
+ rubyize_keys(body) if body.is_a? Hash
9
+ end
10
+
11
+ def parse_response?(env)
12
+ env[:body].is_a? Hash
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,41 @@
1
+ module NetProspex
2
+ module QueryMethods
3
+ def find_person(query)
4
+ response = get('/person/profile.json', query)
5
+ store_balance(response)
6
+ if p = response.fetch(:response,{}).fetch(:person_profile,{})[:person]
7
+ return NetProspex::Api::Person.new(p)
8
+ else
9
+ return nil
10
+ end
11
+ end
12
+
13
+ def find_person_by_id(id)
14
+ find_person(person_id: id)
15
+ end
16
+
17
+ def find_person_by_email(email)
18
+ find_person(email: email)
19
+ end
20
+
21
+ def find_people(query)
22
+ # these are boolean but the API wants 0 or 1
23
+ [:calc_found_rows, :preview].each do |k|
24
+ query[k] = 1 if query[k]
25
+ end
26
+ response = get('/person/list.json', query)
27
+ store_balance(response)
28
+ if persons = response.fetch(:response,{}).fetch(:person_list,{})[:persons]
29
+ return persons.map{|p| NetProspex::Api::Person.new(p)}
30
+ else
31
+ return [] #TODO should this raise an error?
32
+ end
33
+ end
34
+
35
+ protected
36
+ def store_balance(hash)
37
+ balance = hash.fetch(:response,{}).fetch(:transaction,{})[:account_end_balance]
38
+ @account_balance = balance if balance
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ module NetProspex
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'netprospex/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'netprospex-ruby'
8
+ gem.version = NetProspex::VERSION
9
+ gem.authors = ['Michael Limiero']
10
+ gem.email = ['mike5713@gmail.com']
11
+ gem.homepage = 'https://github.com/SalesLoft/netprospex-ruby'
12
+ gem.summary = %q{Ruby bindings for NetProspex API}
13
+ gem.description = %q{The NetProspex API provides search and lookup for detailed information on people and companies.}
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ['lib']
20
+
21
+ gem.add_development_dependency 'bundler', '~> 1.3'
22
+ gem.add_development_dependency 'rake'
23
+ gem.add_development_dependency 'rspec'
24
+ gem.add_development_dependency 'webmock'
25
+ gem.add_development_dependency 'vcr'
26
+ gem.add_runtime_dependency 'activesupport'
27
+ gem.add_runtime_dependency 'faraday'
28
+ gem.add_runtime_dependency 'faraday_middleware'
29
+ gem.add_runtime_dependency 'json'
30
+ gem.add_runtime_dependency 'simple_oauth'
31
+ end