neustar-ws_get_data 0.0.1
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 +7 -0
- data/.gitignore +39 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +21 -0
- data/LICENSE +20 -0
- data/README.md +48 -0
- data/Rakefile +34 -0
- data/lib/neustar-ws_get_data.rb +25 -0
- data/lib/neustar-ws_get_data/client.rb +115 -0
- data/lib/neustar-ws_get_data/elements/phone_attributes.rb +168 -0
- data/lib/neustar-ws_get_data/version.rb +6 -0
- data/neustar-ws_get_data.gemspec +30 -0
- data/spec/fixtures/fault.xml +12 -0
- data/spec/fixtures/improper_fault.xml +11 -0
- data/spec/fixtures/phone_attributes_success.xml +21 -0
- data/spec/lib/neustar-ws_get_data/client_spec.rb +139 -0
- data/spec/lib/neustar-ws_get_data/elements/phone_attributes_spec.rb +96 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/savon.rb +25 -0
- data/tmp/metric_fu/_data/20131021.yml +1028 -0
- data/tmp/metric_fu/_data/20131022.yml +969 -0
- metadata +160 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6d875a60812405cf6e3884324a776d0115fb7c17
|
4
|
+
data.tar.gz: fd7751d2ff95aff549a23d1f18272fe9dff93e0d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7545c58a95d222b7e2731cc35306362b716ebbf93fe54d090892a6870646995ef0eb8df9cccd5576e276dd98f464992b24678ca9ea0c4083c86e6c9825eaeb80
|
7
|
+
data.tar.gz: 9b97220f9ab3314b97aaa24f4cda7bc3fc65dc439a6d543a608b61882b99cff1d515055cb5845abf6f41a86a252cc974e27572549e27a520ad29825fd7a20a7a
|
data/.gitignore
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# SimpleCov generated
|
2
|
+
coverage
|
3
|
+
coverage.data
|
4
|
+
|
5
|
+
# rdoc generated
|
6
|
+
rdoc
|
7
|
+
|
8
|
+
# yard generated
|
9
|
+
doc
|
10
|
+
.yardoc
|
11
|
+
_yardoc
|
12
|
+
|
13
|
+
# bundler
|
14
|
+
.bundle
|
15
|
+
|
16
|
+
# jeweler generated
|
17
|
+
pkg
|
18
|
+
|
19
|
+
# For MacOS:
|
20
|
+
.DS_Store
|
21
|
+
|
22
|
+
# exclude everything in tmp
|
23
|
+
tmp/*
|
24
|
+
# except the metric_fu directory
|
25
|
+
!tmp/metric_fu/
|
26
|
+
# but exclude everything *in* the metric_fu directory
|
27
|
+
tmp/metric_fu/*
|
28
|
+
# except for the _data directory to track metrical outputs
|
29
|
+
!tmp/metric_fu/_data/
|
30
|
+
|
31
|
+
*.gem
|
32
|
+
*.rbc
|
33
|
+
.config
|
34
|
+
Gemfile.lock
|
35
|
+
InstalledFiles
|
36
|
+
lib/bundler/man
|
37
|
+
spec/reports
|
38
|
+
test/tmp
|
39
|
+
test/version_tmp
|
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
neustar-ws_get_data
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0-p247
|
data/Gemfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem 'savon', '~> 2.2'
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem "yard"
|
7
|
+
gem "bundler"
|
8
|
+
end
|
9
|
+
|
10
|
+
group :development, :test do
|
11
|
+
gem "rspec", "~> 2.14.0"
|
12
|
+
gem 'rake', :require => false
|
13
|
+
|
14
|
+
# code metrics:
|
15
|
+
gem "metric_fu"
|
16
|
+
end
|
17
|
+
|
18
|
+
group :test do
|
19
|
+
gem 'simplecov' , :require => false
|
20
|
+
gem 'simplecov-rcov-text', :require => false
|
21
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 TMXCredit, author Zach Belzer
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Neustar::WsGetData
|
2
|
+
|
3
|
+
This gem wraps the SOAP interface for Neustar's WS-GetData Services. It
|
4
|
+
supports both interactive and batch queries.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'neustar-ws_get_data'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
gem install neustar-ws_get_data
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
client = Neustar::WsGetData::Client.new(
|
24
|
+
:username => 'username',
|
25
|
+
:password => 'password',
|
26
|
+
:service_id => 123456
|
27
|
+
)
|
28
|
+
|
29
|
+
client.operations
|
30
|
+
#=> [:query, :batch_query]
|
31
|
+
|
32
|
+
client.phone_attributes('8583145300', [:phone_type])
|
33
|
+
#=> {:phone_type => :wireless}
|
34
|
+
|
35
|
+
client.phone_attributes('8583145300')
|
36
|
+
#=> {:prepaid_phone => false,
|
37
|
+
:business_phone => :unknown,
|
38
|
+
:phone_in_service => "Active for 1 month or less",
|
39
|
+
:phone_type => :wireless}
|
40
|
+
```
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
1. Fork it
|
45
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
46
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
47
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
48
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
require 'rake'
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
require './lib/neustar-ws_get_data/version'
|
9
|
+
|
10
|
+
begin
|
11
|
+
Bundler.setup(:default, :development)
|
12
|
+
rescue Bundler::BundlerError => e
|
13
|
+
$stderr.puts e.message
|
14
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
15
|
+
exit e.status_code
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
19
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => :spec
|
23
|
+
|
24
|
+
desc "Release tag for this version to github"
|
25
|
+
task "git:release" do
|
26
|
+
`git tag v#{Neustar::WsGetData::VERSION}`
|
27
|
+
`git push --tags`
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Build and push gem to rubygems"
|
31
|
+
task "build" do
|
32
|
+
`gem build neustar-ws_get_data.gemspec`
|
33
|
+
`gem push neustar-ws_get_data-#{Neustar::WsGetData::VERSION}.gem`
|
34
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'savon'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
# Top-level namespace.
|
5
|
+
module Neustar
|
6
|
+
# Wrapper to interface with the WS-GetData Service.
|
7
|
+
module WsGetData
|
8
|
+
# Location of SOAP WSDL for WS-GetData:
|
9
|
+
WSDL = 'http://webapp.targusinfo.com/ws-getdata/query.asmx?WSDL'
|
10
|
+
end
|
11
|
+
|
12
|
+
# Top-level error class for Neustar.
|
13
|
+
class Error < StandardError
|
14
|
+
end
|
15
|
+
|
16
|
+
# Error to be raised when basic configuration is missing.
|
17
|
+
class ConfigurationError < Error
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
require File.expand_path("../neustar-ws_get_data/version", __FILE__)
|
22
|
+
require File.expand_path("../neustar-ws_get_data/client", __FILE__)
|
23
|
+
|
24
|
+
elements = File.expand_path("../neustar-ws_get_data/elements/*", __FILE__)
|
25
|
+
Dir[elements].each {|element| require element }
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# Base client used to interface with WS-GetData query and batch_query services.
|
2
|
+
class Neustar::WsGetData::Client
|
3
|
+
# Maximum transaction ID:
|
4
|
+
MAX_TRANSACTION_ID = 1_000_000
|
5
|
+
|
6
|
+
# @param [Hash] options The configuration options
|
7
|
+
# @option options [String] :username Name of the Neustar account
|
8
|
+
# @option options [String] :password Password for the Neustar account
|
9
|
+
# @option options [String] ::service_id Service ID for the Neustar account
|
10
|
+
def initialize(options = {})
|
11
|
+
@service = Savon.client(:wsdl => Neustar::WsGetData::WSDL)
|
12
|
+
@username = options[:username] or
|
13
|
+
raise ConfigurationError, "Username required"
|
14
|
+
@password = options[:password] or
|
15
|
+
raise ConfigurationError, "Password required"
|
16
|
+
@service_id = options[:service_id] or
|
17
|
+
raise ConfigurationError, "Service ID required"
|
18
|
+
end
|
19
|
+
|
20
|
+
# List the operations available to the client.
|
21
|
+
#
|
22
|
+
# @return [Array<Symbol>]
|
23
|
+
def operations
|
24
|
+
@service.operations
|
25
|
+
end
|
26
|
+
|
27
|
+
# Execute an 'interactive' query.
|
28
|
+
#
|
29
|
+
# @param [Hash] params
|
30
|
+
# @return [Hash]
|
31
|
+
def query(params)
|
32
|
+
call(:query, params)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Execute a batch query.
|
36
|
+
#
|
37
|
+
# @param [Hash] params
|
38
|
+
# @return [Hash]
|
39
|
+
def batch_query(params)
|
40
|
+
call(:batch_query, params)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Execute a call to the given service type.
|
44
|
+
#
|
45
|
+
# @param [Symbol] service
|
46
|
+
# @return [Hash]
|
47
|
+
def call(service, params)
|
48
|
+
transaction_id = params.fetch(:transaction_id) { build_transaction_id }
|
49
|
+
|
50
|
+
message = origination_params.
|
51
|
+
merge(:transId => transaction_id).
|
52
|
+
merge(params)
|
53
|
+
|
54
|
+
begin
|
55
|
+
response = @service.call(service, :message => message)
|
56
|
+
process_response(service, response)
|
57
|
+
rescue Savon::SOAPFault => error
|
58
|
+
raise Neustar::Error, extract_fault_message(error)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Execute initial post-processing and error handling on the response.
|
63
|
+
#
|
64
|
+
# @param [Symbol] service
|
65
|
+
# @param [Savon::Response] response
|
66
|
+
#
|
67
|
+
# @return [Hash]
|
68
|
+
def process_response(service, response)
|
69
|
+
response_wrapper = response.body[:"#{service}_response"]
|
70
|
+
response_wrapper && response_wrapper[:response]
|
71
|
+
end
|
72
|
+
|
73
|
+
# Helper to access PhoneAttributes element.
|
74
|
+
# TODO: Refactor out of here
|
75
|
+
#
|
76
|
+
# @param [#to_s] phone_number
|
77
|
+
# @param [Array<Symbol>] indicators
|
78
|
+
def phone_attributes(phone_number, indicators = [])
|
79
|
+
Neustar::WsGetData::PhoneAttributes.query(self, phone_number, indicators)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Parameters used to authenticate the client.
|
83
|
+
#
|
84
|
+
# @return [Hash]
|
85
|
+
def origination_params
|
86
|
+
{
|
87
|
+
:origination => {
|
88
|
+
:username => @username, :password => @password
|
89
|
+
},
|
90
|
+
:serviceId => @service_id.to_s
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns a unique transaction ID to send with each request.
|
95
|
+
#
|
96
|
+
# @return [String]
|
97
|
+
def build_transaction_id
|
98
|
+
SecureRandom.random_number(MAX_TRANSACTION_ID)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Pulls the error message from a Savon::SOAPFault exception.
|
102
|
+
#
|
103
|
+
# @param [Savon::SOAPFault] error
|
104
|
+
# @return [String]
|
105
|
+
def extract_fault_message(error)
|
106
|
+
data = error.to_hash
|
107
|
+
|
108
|
+
if (fault = data[:fault]) and (faultstring = fault[:faultstring]) then
|
109
|
+
faultstring
|
110
|
+
else
|
111
|
+
"Unknown Error"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
private :extract_fault_message
|
115
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# From the documentation:
|
2
|
+
#
|
3
|
+
# "Element ID 1320 accepts a phone number and returns attributes associated
|
4
|
+
# with the phone number. Currently, the following attributes are available:
|
5
|
+
# Prepaid Phone Indicator, Business Phone Indicator (BPI), Phone In-Service
|
6
|
+
# Indicator, and Phone Type Indicator."
|
7
|
+
module Neustar::WsGetData::PhoneAttributes
|
8
|
+
extend self
|
9
|
+
|
10
|
+
# Error raised when an invalid phone number is sent to the service.
|
11
|
+
class OutOfDomainError < Neustar::Error; end
|
12
|
+
|
13
|
+
# ID for "Phone Attributes".
|
14
|
+
ELEMENT_ID = 1320
|
15
|
+
|
16
|
+
# Service ID to specify the telephone number in a request.
|
17
|
+
TELEPHONE_SPECIFICATION_SERVICE_ID = 1
|
18
|
+
|
19
|
+
# Service ID to specify which attributes we want returned.
|
20
|
+
PHONE_ATTRIBUTES_REQUESTED_SERVICE_ID = 599
|
21
|
+
|
22
|
+
# Mappings to request certain indicators from the service.
|
23
|
+
INDICATORS = {
|
24
|
+
:prepaid_phone => 1,
|
25
|
+
:business_phone => 2,
|
26
|
+
:phone_in_service => 3,
|
27
|
+
:phone_type => 4,
|
28
|
+
}
|
29
|
+
|
30
|
+
# Whether or not a phone is prepaid.
|
31
|
+
PREPAID_PHONE_ATTRIBUTE_MAP = {
|
32
|
+
'Y' => true,
|
33
|
+
'N' => false
|
34
|
+
}
|
35
|
+
|
36
|
+
# The assumed purpose for a phone.
|
37
|
+
BUSINESS_PHONE_INDICATOR_MAP = {
|
38
|
+
'B' => :business_phone,
|
39
|
+
'C' => :residential_phone,
|
40
|
+
'D' => :dual_phone,
|
41
|
+
'U' => :unknown
|
42
|
+
}
|
43
|
+
|
44
|
+
# The Phone In-Service field indicates whether the phone is active and
|
45
|
+
# provides a range indicator for the active/inactive status.
|
46
|
+
PHONE_IN_SERVICE_INDICATOR_MAP = {
|
47
|
+
'A1' => "Active for 1 month or less",
|
48
|
+
'A2' => "Active for 2 months",
|
49
|
+
'A3' => "Active for 3 months",
|
50
|
+
'A4' => "Active for between 4-6 months",
|
51
|
+
'A5' => "Active for between 7-9 months",
|
52
|
+
'A6' => "Active for between 10-11 months",
|
53
|
+
'A7' => "Active for 12 months or longer",
|
54
|
+
'I1' => "Inactive for 1 month or less",
|
55
|
+
'I2' => "Inactive for 2 months",
|
56
|
+
'I3' => "Inactive for 3 months",
|
57
|
+
'I4' => "Inactive for between 4-6 months",
|
58
|
+
'I5' => "Inactive for between 7-9 months",
|
59
|
+
'I6' => "Inactive for between 10-11 months",
|
60
|
+
'I7' => "Inactive for 12 months or longer",
|
61
|
+
'U' => "Status Unknown",
|
62
|
+
}
|
63
|
+
|
64
|
+
# The type of phone used.
|
65
|
+
PHONE_TYPE_INDICATOR_MAP = {
|
66
|
+
'W' => :wireless,
|
67
|
+
'L' => :landline,
|
68
|
+
'U' => :unknown
|
69
|
+
}
|
70
|
+
|
71
|
+
# A map between each attribute and their possible values.
|
72
|
+
INDICATOR_MAPPINGS = {
|
73
|
+
:prepaid_phone => PREPAID_PHONE_ATTRIBUTE_MAP,
|
74
|
+
:business_phone => BUSINESS_PHONE_INDICATOR_MAP,
|
75
|
+
:phone_in_service => PHONE_IN_SERVICE_INDICATOR_MAP,
|
76
|
+
:phone_type => PHONE_TYPE_INDICATOR_MAP
|
77
|
+
}
|
78
|
+
|
79
|
+
# Indicates that an invalid phone number was sent to the service.
|
80
|
+
OUT_OF_DOMAIN_ERROR = "6"
|
81
|
+
|
82
|
+
# Method used to execute a query against the Phone Attributes element of the
|
83
|
+
# WS-GetData Service.
|
84
|
+
#
|
85
|
+
# @param [Neustar::WsGetData::Client] client
|
86
|
+
# @param [#to_s] phone_number
|
87
|
+
# @param [Array<Symbol>] indicators
|
88
|
+
#
|
89
|
+
# @return [Hash]
|
90
|
+
def query(client, phone_number, indicators = [])
|
91
|
+
indicators = parse_indicators(indicators)
|
92
|
+
|
93
|
+
params = {
|
94
|
+
:phone_number => phone_number,
|
95
|
+
:indicators => indicators
|
96
|
+
}
|
97
|
+
|
98
|
+
process_response(execute_request(client, params), params)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Assemble and execute a query using the passed client.
|
102
|
+
#
|
103
|
+
# @param [Neustar::WsGetData::Client] client
|
104
|
+
# @param [Hash] params
|
105
|
+
# @option params [String] :phone_number
|
106
|
+
# @option params [String] :indicators
|
107
|
+
#
|
108
|
+
# @return [Hash]
|
109
|
+
def execute_request(client, params)
|
110
|
+
client.query(
|
111
|
+
:elements => { :id => ELEMENT_ID },
|
112
|
+
:serviceKeys => {
|
113
|
+
:serviceKey => [
|
114
|
+
{
|
115
|
+
:id => TELEPHONE_SPECIFICATION_SERVICE_ID,
|
116
|
+
:value => params[:phone_number]
|
117
|
+
},
|
118
|
+
{
|
119
|
+
:id => PHONE_ATTRIBUTES_REQUESTED_SERVICE_ID,
|
120
|
+
:value => params[:indicators]
|
121
|
+
}
|
122
|
+
]
|
123
|
+
}
|
124
|
+
)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Do element specific processing on response from client.
|
128
|
+
#
|
129
|
+
# @param [Hash] response
|
130
|
+
# @option response [String] :error_code The stringified number
|
131
|
+
# of the error code
|
132
|
+
# @option response [Hash] :result
|
133
|
+
# @param [Hash] params
|
134
|
+
# @option params [String] :phone_number
|
135
|
+
#
|
136
|
+
# @return [Hash]
|
137
|
+
def process_response(response, params)
|
138
|
+
if response[:error_code] == OUT_OF_DOMAIN_ERROR
|
139
|
+
raise OutOfDomainError, params[:phone_number]
|
140
|
+
else
|
141
|
+
string = response[:result][:element][:value]
|
142
|
+
result = {}
|
143
|
+
|
144
|
+
INDICATOR_MAPPINGS.each do |name, mapping|
|
145
|
+
mapping.detect do |key, value|
|
146
|
+
result[name] = value if string.index(key)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
result
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Given a list of indicator symbols, derive the argument to send the service.
|
155
|
+
#
|
156
|
+
# @param [Array<Symbol>] indicators
|
157
|
+
# @return [String]
|
158
|
+
def parse_indicators(indicators)
|
159
|
+
vals =
|
160
|
+
if indicators.empty?
|
161
|
+
INDICATORS.values
|
162
|
+
else
|
163
|
+
INDICATORS.values_at(*indicators)
|
164
|
+
end
|
165
|
+
|
166
|
+
vals.join(',')
|
167
|
+
end
|
168
|
+
end
|