geocoder 1.6.6 → 1.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -2
- data/README.md +318 -206
- data/lib/generators/geocoder/config/templates/initializer.rb +7 -1
- data/lib/geocoder/cache.rb +12 -33
- data/lib/geocoder/cache_stores/base.rb +40 -0
- data/lib/geocoder/cache_stores/generic.rb +35 -0
- data/lib/geocoder/cache_stores/redis.rb +34 -0
- data/lib/geocoder/configuration.rb +7 -2
- data/lib/geocoder/ip_address.rb +6 -0
- data/lib/geocoder/lookup.rb +16 -2
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/amazon_location_service.rb +54 -0
- data/lib/geocoder/lookups/base.rb +8 -2
- data/lib/geocoder/lookups/bing.rb +1 -1
- data/lib/geocoder/lookups/geoapify.rb +72 -0
- data/lib/geocoder/lookups/geoip2.rb +4 -0
- data/lib/geocoder/lookups/ip2location.rb +10 -6
- data/lib/geocoder/lookups/ipdata_co.rb +1 -1
- data/lib/geocoder/lookups/ipqualityscore.rb +50 -0
- data/lib/geocoder/lookups/melissa_street.rb +41 -0
- data/lib/geocoder/lookups/photon.rb +89 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +1 -1
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/amazon_location_service.rb +57 -0
- data/lib/geocoder/results/esri.rb +5 -2
- data/lib/geocoder/results/geoapify.rb +179 -0
- data/lib/geocoder/results/ipqualityscore.rb +54 -0
- data/lib/geocoder/results/mapbox.rb +10 -4
- data/lib/geocoder/results/melissa_street.rb +46 -0
- data/lib/geocoder/results/photon.rb +119 -0
- data/lib/geocoder/version.rb +1 -1
- metadata +17 -2
@@ -9,7 +9,7 @@ Geocoder.configure(
|
|
9
9
|
# https_proxy: nil, # HTTPS proxy server (user:pass@host:port)
|
10
10
|
# api_key: nil, # API key for geocoding service
|
11
11
|
# cache: nil, # cache object (must respond to #[], #[]=, and #del)
|
12
|
-
# cache_prefix: 'geocoder:', #
|
12
|
+
# cache_prefix: 'geocoder:', # DEPRECATED, please use cache_options[:prefix] instead
|
13
13
|
|
14
14
|
# Exceptions that should not be rescued by default
|
15
15
|
# (if you want to implement custom error handling);
|
@@ -19,4 +19,10 @@ Geocoder.configure(
|
|
19
19
|
# Calculation options
|
20
20
|
# units: :mi, # :km for kilometers or :mi for miles
|
21
21
|
# distances: :linear # :spherical or :linear
|
22
|
+
|
23
|
+
# Cache configuration
|
24
|
+
# cache_options: {
|
25
|
+
# expiration: 2.days,
|
26
|
+
# prefix: 'geocoder:'
|
27
|
+
# }
|
22
28
|
)
|
data/lib/geocoder/cache.rb
CHANGED
@@ -1,23 +1,18 @@
|
|
1
|
+
Dir["#{__dir__}/cache_stores/*.rb"].each {|file| require file }
|
2
|
+
|
1
3
|
module Geocoder
|
2
4
|
class Cache
|
3
5
|
|
4
|
-
def initialize(store,
|
5
|
-
@
|
6
|
-
@
|
6
|
+
def initialize(store, config)
|
7
|
+
@class = (Object.const_get("Geocoder::CacheStore::#{store.class}") rescue Geocoder::CacheStore::Generic)
|
8
|
+
@store_service = @class.new(store, config)
|
7
9
|
end
|
8
10
|
|
9
11
|
##
|
10
12
|
# Read from the Cache.
|
11
13
|
#
|
12
14
|
def [](url)
|
13
|
-
interpret
|
14
|
-
when store.respond_to?(:[])
|
15
|
-
store[key_for(url)]
|
16
|
-
when store.respond_to?(:get)
|
17
|
-
store.get key_for(url)
|
18
|
-
when store.respond_to?(:read)
|
19
|
-
store.read key_for(url)
|
20
|
-
end
|
15
|
+
interpret store_service.read(url)
|
21
16
|
rescue => e
|
22
17
|
warn "Geocoder cache read error: #{e}"
|
23
18
|
end
|
@@ -26,14 +21,7 @@ module Geocoder
|
|
26
21
|
# Write to the Cache.
|
27
22
|
#
|
28
23
|
def []=(url, value)
|
29
|
-
|
30
|
-
when store.respond_to?(:[]=)
|
31
|
-
store[key_for(url)] = value
|
32
|
-
when store.respond_to?(:set)
|
33
|
-
store.set key_for(url), value
|
34
|
-
when store.respond_to?(:write)
|
35
|
-
store.write key_for(url), value
|
36
|
-
end
|
24
|
+
store_service.write(url, value)
|
37
25
|
rescue => e
|
38
26
|
warn "Geocoder cache write error: #{e}"
|
39
27
|
end
|
@@ -44,7 +32,7 @@ module Geocoder
|
|
44
32
|
#
|
45
33
|
def expire(url)
|
46
34
|
if url == :all
|
47
|
-
if
|
35
|
+
if store_service.respond_to?(:keys)
|
48
36
|
urls.each{ |u| expire(u) }
|
49
37
|
else
|
50
38
|
raise(NoMethodError, "The Geocoder cache store must implement `#keys` for `expire(:all)` to work")
|
@@ -57,29 +45,21 @@ module Geocoder
|
|
57
45
|
|
58
46
|
private # ----------------------------------------------------------------
|
59
47
|
|
60
|
-
def
|
61
|
-
def store; @store; end
|
62
|
-
|
63
|
-
##
|
64
|
-
# Cache key for a given URL.
|
65
|
-
#
|
66
|
-
def key_for(url)
|
67
|
-
[prefix, url].join
|
68
|
-
end
|
48
|
+
def store_service; @store_service; end
|
69
49
|
|
70
50
|
##
|
71
51
|
# Array of keys with the currently configured prefix
|
72
52
|
# that have non-nil values.
|
73
53
|
#
|
74
54
|
def keys
|
75
|
-
|
55
|
+
store_service.keys
|
76
56
|
end
|
77
57
|
|
78
58
|
##
|
79
59
|
# Array of cached URLs.
|
80
60
|
#
|
81
61
|
def urls
|
82
|
-
|
62
|
+
store_service.urls
|
83
63
|
end
|
84
64
|
|
85
65
|
##
|
@@ -91,8 +71,7 @@ module Geocoder
|
|
91
71
|
end
|
92
72
|
|
93
73
|
def expire_single_url(url)
|
94
|
-
|
95
|
-
store.respond_to?(:del) ? store.del(key) : store.delete(key)
|
74
|
+
store_service.remove(url)
|
96
75
|
end
|
97
76
|
end
|
98
77
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Geocoder::CacheStore
|
2
|
+
class Base
|
3
|
+
def initialize(store, options)
|
4
|
+
@store = store
|
5
|
+
@config = options
|
6
|
+
@prefix = config[:prefix]
|
7
|
+
end
|
8
|
+
|
9
|
+
##
|
10
|
+
# Array of keys with the currently configured prefix
|
11
|
+
# that have non-nil values.
|
12
|
+
def keys
|
13
|
+
store.keys.select { |k| k.match(/^#{prefix}/) and self[k] }
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Array of cached URLs.
|
18
|
+
#
|
19
|
+
def urls
|
20
|
+
keys
|
21
|
+
end
|
22
|
+
|
23
|
+
protected # ----------------------------------------------------------------
|
24
|
+
|
25
|
+
def prefix; @prefix; end
|
26
|
+
def store; @store; end
|
27
|
+
def config; @config; end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Cache key for a given URL.
|
31
|
+
#
|
32
|
+
def key_for(url)
|
33
|
+
if url.match(/^#{prefix}/)
|
34
|
+
url
|
35
|
+
else
|
36
|
+
[prefix, url].join
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'geocoder/cache_stores/base'
|
2
|
+
|
3
|
+
module Geocoder::CacheStore
|
4
|
+
class Generic < Base
|
5
|
+
def write(url, value)
|
6
|
+
case
|
7
|
+
when store.respond_to?(:[]=)
|
8
|
+
store[key_for(url)] = value
|
9
|
+
when store.respond_to?(:set)
|
10
|
+
store.set key_for(url), value
|
11
|
+
when store.respond_to?(:write)
|
12
|
+
store.write key_for(url), value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def read(url)
|
17
|
+
case
|
18
|
+
when store.respond_to?(:[])
|
19
|
+
store[key_for(url)]
|
20
|
+
when store.respond_to?(:get)
|
21
|
+
store.get key_for(url)
|
22
|
+
when store.respond_to?(:read)
|
23
|
+
store.read key_for(url)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def keys
|
28
|
+
store.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
def remove(key)
|
32
|
+
store.delete(key)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'geocoder/cache_stores/base'
|
2
|
+
|
3
|
+
module Geocoder::CacheStore
|
4
|
+
class Redis < Base
|
5
|
+
def initialize(store, options)
|
6
|
+
super
|
7
|
+
@expiration = options[:expiration]
|
8
|
+
end
|
9
|
+
|
10
|
+
def write(url, value, expire = @expiration)
|
11
|
+
if expire.present?
|
12
|
+
store.set key_for(url), value, ex: expire
|
13
|
+
else
|
14
|
+
store.set key_for(url), value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def read(url)
|
19
|
+
store.get key_for(url)
|
20
|
+
end
|
21
|
+
|
22
|
+
def keys
|
23
|
+
store.keys("#{prefix}*")
|
24
|
+
end
|
25
|
+
|
26
|
+
def remove(key)
|
27
|
+
store.del(key)
|
28
|
+
end
|
29
|
+
|
30
|
+
private # ----------------------------------------------------------------
|
31
|
+
|
32
|
+
def expire; @expiration; end
|
33
|
+
end
|
34
|
+
end
|
@@ -55,6 +55,7 @@ module Geocoder
|
|
55
55
|
:lookup,
|
56
56
|
:ip_lookup,
|
57
57
|
:language,
|
58
|
+
:host,
|
58
59
|
:http_headers,
|
59
60
|
:use_https,
|
60
61
|
:http_proxy,
|
@@ -67,7 +68,8 @@ module Geocoder
|
|
67
68
|
:distances,
|
68
69
|
:basic_auth,
|
69
70
|
:logger,
|
70
|
-
:kernel_logger_level
|
71
|
+
:kernel_logger_level,
|
72
|
+
:cache_options
|
71
73
|
]
|
72
74
|
|
73
75
|
attr_accessor :data
|
@@ -107,7 +109,7 @@ module Geocoder
|
|
107
109
|
@data[:https_proxy] = nil # HTTPS proxy server (user:pass@host:port)
|
108
110
|
@data[:api_key] = nil # API key for geocoding service
|
109
111
|
@data[:cache] = nil # cache object (must respond to #[], #[]=, and #keys)
|
110
|
-
@data[:cache_prefix] = "geocoder:" # prefix (string) to use for all cache keys
|
112
|
+
@data[:cache_prefix] = "geocoder:" # - DEPRECATED - prefix (string) to use for all cache keys
|
111
113
|
@data[:basic_auth] = {} # user and password for basic auth ({:user => "user", :password => "password"})
|
112
114
|
@data[:logger] = :kernel # :kernel or Logger instance
|
113
115
|
@data[:kernel_logger_level] = ::Logger::WARN # log level, if kernel logger is used
|
@@ -120,6 +122,9 @@ module Geocoder
|
|
120
122
|
# calculation options
|
121
123
|
@data[:units] = :mi # :mi or :km
|
122
124
|
@data[:distances] = :linear # :linear or :spherical
|
125
|
+
|
126
|
+
# explicit cache service options
|
127
|
+
@data[:cache_options] = {}
|
123
128
|
end
|
124
129
|
|
125
130
|
instance_eval(OPTIONS.map do |option|
|
data/lib/geocoder/ip_address.rb
CHANGED
data/lib/geocoder/lookup.rb
CHANGED
@@ -18,6 +18,14 @@ module Geocoder
|
|
18
18
|
all_services - [:test]
|
19
19
|
end
|
20
20
|
|
21
|
+
##
|
22
|
+
# Array of valid Lookup service names, excluding any that do not build their own HTTP requests.
|
23
|
+
# For example, Amazon Location Service uses the AWS gem, not HTTP REST requests, to fetch data.
|
24
|
+
#
|
25
|
+
def all_services_with_http_requests
|
26
|
+
all_services_except_test - [:amazon_location_service]
|
27
|
+
end
|
28
|
+
|
21
29
|
##
|
22
30
|
# All street address lookup services, default first.
|
23
31
|
#
|
@@ -53,7 +61,11 @@ module Geocoder
|
|
53
61
|
:test,
|
54
62
|
:latlon,
|
55
63
|
:amap,
|
56
|
-
:osmnames
|
64
|
+
:osmnames,
|
65
|
+
:melissa_street,
|
66
|
+
:amazon_location_service,
|
67
|
+
:geoapify,
|
68
|
+
:photon
|
57
69
|
]
|
58
70
|
end
|
59
71
|
|
@@ -63,6 +75,7 @@ module Geocoder
|
|
63
75
|
def ip_services
|
64
76
|
@ip_services ||= [
|
65
77
|
:baidu_ip,
|
78
|
+
:abstract_api,
|
66
79
|
:freegeoip,
|
67
80
|
:geoip2,
|
68
81
|
:maxmind,
|
@@ -77,7 +90,8 @@ module Geocoder
|
|
77
90
|
:db_ip_com,
|
78
91
|
:ipstack,
|
79
92
|
:ip2location,
|
80
|
-
:ipgeolocation
|
93
|
+
:ipgeolocation,
|
94
|
+
:ipqualityscore
|
81
95
|
]
|
82
96
|
end
|
83
97
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'geocoder/lookups/base'
|
4
|
+
require 'geocoder/results/abstract_api'
|
5
|
+
|
6
|
+
module Geocoder::Lookup
|
7
|
+
class AbstractApi < Base
|
8
|
+
|
9
|
+
def name
|
10
|
+
"Abstract API"
|
11
|
+
end
|
12
|
+
|
13
|
+
def required_api_key_parts
|
14
|
+
['api_key']
|
15
|
+
end
|
16
|
+
|
17
|
+
def supported_protocols
|
18
|
+
[:https]
|
19
|
+
end
|
20
|
+
|
21
|
+
private # ---------------------------------------------------------------
|
22
|
+
|
23
|
+
def base_query_url(query)
|
24
|
+
"#{protocol}://ipgeolocation.abstractapi.com/v1/?"
|
25
|
+
end
|
26
|
+
|
27
|
+
def query_url_params(query)
|
28
|
+
params = {api_key: configuration.api_key}
|
29
|
+
|
30
|
+
ip_address = query.sanitized_text
|
31
|
+
if ip_address.is_a?(String) && ip_address.length > 0
|
32
|
+
params[:ip_address] = ip_address
|
33
|
+
end
|
34
|
+
|
35
|
+
params.merge(super)
|
36
|
+
end
|
37
|
+
|
38
|
+
def results(query, reverse = false)
|
39
|
+
if doc = fetch_data(query)
|
40
|
+
[doc]
|
41
|
+
else
|
42
|
+
[]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/amazon_location_service'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class AmazonLocationService < Base
|
6
|
+
def results(query)
|
7
|
+
params = query.options.dup
|
8
|
+
|
9
|
+
# index_name is required
|
10
|
+
# Aws::ParamValidator raises ArgumentError on missing required keys
|
11
|
+
params.merge!(index_name: configuration[:index_name])
|
12
|
+
|
13
|
+
# Aws::ParamValidator raises ArgumentError on unexpected keys
|
14
|
+
params.delete(:lookup)
|
15
|
+
|
16
|
+
resp = if query.reverse_geocode?
|
17
|
+
client.search_place_index_for_position(params.merge(position: query.coordinates.reverse))
|
18
|
+
else
|
19
|
+
client.search_place_index_for_text(params.merge(text: query.text))
|
20
|
+
end
|
21
|
+
|
22
|
+
resp.results.map(&:place)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def client
|
28
|
+
return @client if @client
|
29
|
+
require_sdk
|
30
|
+
keys = configuration.api_key
|
31
|
+
if keys
|
32
|
+
@client = Aws::LocationService::Client.new(
|
33
|
+
access_key_id: keys[:access_key_id],
|
34
|
+
secret_access_key: keys[:secret_access_key],
|
35
|
+
)
|
36
|
+
else
|
37
|
+
@client = Aws::LocationService::Client.new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def require_sdk
|
42
|
+
begin
|
43
|
+
require 'aws-sdk-locationservice'
|
44
|
+
rescue LoadError
|
45
|
+
raise_error(Geocoder::ConfigurationError) ||
|
46
|
+
Geocoder.log(
|
47
|
+
:error,
|
48
|
+
"Couldn't load the Amazon Location Service SDK. " +
|
49
|
+
"Install it with: gem install aws-sdk-locationservice -v '~> 1.4'"
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -83,8 +83,14 @@ module Geocoder
|
|
83
83
|
# The working Cache object.
|
84
84
|
#
|
85
85
|
def cache
|
86
|
-
if @cache.nil?
|
87
|
-
|
86
|
+
if @cache.nil? && (store = configuration.cache)
|
87
|
+
cache_options = configuration.cache_options
|
88
|
+
cache_prefix = (configuration.cache_prefix rescue false)
|
89
|
+
if cache_prefix
|
90
|
+
cache_options[:prefix] ||= configuration.cache_prefix
|
91
|
+
warn '[Geocoder] cache_prefix is deprecated, please change to cache_options.prefix instead'
|
92
|
+
end
|
93
|
+
@cache = Cache.new(store, cache_options)
|
88
94
|
end
|
89
95
|
@cache
|
90
96
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'geocoder/lookups/base'
|
4
|
+
require 'geocoder/results/geoapify'
|
5
|
+
|
6
|
+
module Geocoder
|
7
|
+
module Lookup
|
8
|
+
# https://apidocs.geoapify.com/docs/geocoding/api
|
9
|
+
class Geoapify < Base
|
10
|
+
def name
|
11
|
+
'Geoapify'
|
12
|
+
end
|
13
|
+
|
14
|
+
def required_api_key_parts
|
15
|
+
['api_key']
|
16
|
+
end
|
17
|
+
|
18
|
+
def supported_protocols
|
19
|
+
[:https]
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def base_query_url(query)
|
25
|
+
method = query.reverse_geocode? ? 'reverse' : 'search'
|
26
|
+
"https://api.geoapify.com/v1/geocode/#{method}?"
|
27
|
+
end
|
28
|
+
|
29
|
+
def results(query)
|
30
|
+
return [] unless (doc = fetch_data(query))
|
31
|
+
|
32
|
+
# The rest of the status codes should be already handled by the default
|
33
|
+
# functionality as the API returns correct HTTP response codes in most
|
34
|
+
# cases. There may be some unhandled cases still (such as over query
|
35
|
+
# limit reached) but there is not enough documentation to cover them.
|
36
|
+
case doc['statusCode']
|
37
|
+
when 500
|
38
|
+
raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, doc['message'])
|
39
|
+
end
|
40
|
+
|
41
|
+
return [] unless doc['type'] == 'FeatureCollection'
|
42
|
+
return [] unless doc['features'] || doc['features'].present?
|
43
|
+
|
44
|
+
doc['features']
|
45
|
+
end
|
46
|
+
|
47
|
+
def query_url_params(query)
|
48
|
+
lang = query.language || configuration.language
|
49
|
+
params = { apiKey: configuration.api_key, lang: lang, limit: query.options[:limit] }
|
50
|
+
|
51
|
+
if query.reverse_geocode?
|
52
|
+
params.merge!(query_url_params_reverse(query))
|
53
|
+
else
|
54
|
+
params.merge!(query_url_params_coordinates(query))
|
55
|
+
end
|
56
|
+
|
57
|
+
params.merge!(super)
|
58
|
+
end
|
59
|
+
|
60
|
+
def query_url_params_coordinates(query)
|
61
|
+
{ text: query.sanitized_text }
|
62
|
+
end
|
63
|
+
|
64
|
+
def query_url_params_reverse(query)
|
65
|
+
{
|
66
|
+
lat: query.coordinates[0],
|
67
|
+
lon: query.coordinates[1]
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -37,6 +37,10 @@ module Geocoder
|
|
37
37
|
def results(query)
|
38
38
|
return [] unless configuration[:file]
|
39
39
|
|
40
|
+
if @mmdb.respond_to?(:local_ip_alias) && !configuration[:local_ip_alias].nil?
|
41
|
+
@mmdb.local_ip_alias = configuration[:local_ip_alias]
|
42
|
+
end
|
43
|
+
|
40
44
|
result = @mmdb.lookup(query.to_s)
|
41
45
|
result.nil? ? [] : [result]
|
42
46
|
end
|
@@ -8,6 +8,10 @@ module Geocoder::Lookup
|
|
8
8
|
"IP2LocationApi"
|
9
9
|
end
|
10
10
|
|
11
|
+
def required_api_key_parts
|
12
|
+
['key']
|
13
|
+
end
|
14
|
+
|
11
15
|
def supported_protocols
|
12
16
|
[:http, :https]
|
13
17
|
end
|
@@ -15,15 +19,15 @@ module Geocoder::Lookup
|
|
15
19
|
private # ----------------------------------------------------------------
|
16
20
|
|
17
21
|
def base_query_url(query)
|
18
|
-
"#{protocol}://api.ip2location.com/?"
|
22
|
+
"#{protocol}://api.ip2location.com/v2/?"
|
19
23
|
end
|
20
24
|
|
21
25
|
def query_url_params(query)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
super.merge(
|
27
|
+
key: configuration.api_key,
|
28
|
+
ip: query.sanitized_text,
|
29
|
+
package: configuration[:package],
|
30
|
+
)
|
27
31
|
end
|
28
32
|
|
29
33
|
def results(query)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'geocoder/lookups/base'
|
4
|
+
require 'geocoder/results/ipqualityscore'
|
5
|
+
|
6
|
+
module Geocoder::Lookup
|
7
|
+
class Ipqualityscore < Base
|
8
|
+
|
9
|
+
def name
|
10
|
+
"IPQualityScore"
|
11
|
+
end
|
12
|
+
|
13
|
+
def required_api_key_parts
|
14
|
+
['api_key']
|
15
|
+
end
|
16
|
+
|
17
|
+
private # ---------------------------------------------------------------
|
18
|
+
|
19
|
+
def base_query_url(query)
|
20
|
+
"#{protocol}://ipqualityscore.com/api/json/ip/#{configuration.api_key}/#{query.sanitized_text}?"
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_response?(response)
|
24
|
+
if (json = parse_json(response.body))
|
25
|
+
success = json['success']
|
26
|
+
end
|
27
|
+
super && success == true
|
28
|
+
end
|
29
|
+
|
30
|
+
def results(query, reverse = false)
|
31
|
+
return [] unless doc = fetch_data(query)
|
32
|
+
|
33
|
+
return [doc] if doc['success']
|
34
|
+
|
35
|
+
case doc['message']
|
36
|
+
when /invalid (.*) key/i
|
37
|
+
raise_error Geocoder::InvalidApiKey ||
|
38
|
+
Geocoder.log(:warn, "#{name} API error: invalid api key.")
|
39
|
+
when /insufficient credits/, /exceeded your request quota/
|
40
|
+
raise_error Geocoder::OverQueryLimitError ||
|
41
|
+
Geocoder.log(:warn, "#{name} API error: query limit exceeded.")
|
42
|
+
when /invalid (.*) address/i
|
43
|
+
raise_error Geocoder::InvalidRequest ||
|
44
|
+
Geocoder.log(:warn, "#{name} API error: invalid request.")
|
45
|
+
end
|
46
|
+
|
47
|
+
[doc]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/melissa_street"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class MelissaStreet < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"MelissaStreet"
|
9
|
+
end
|
10
|
+
|
11
|
+
def results(query)
|
12
|
+
return [] unless doc = fetch_data(query)
|
13
|
+
|
14
|
+
if doc["TransmissionResults"] == "GE05"
|
15
|
+
raise_error(Geocoder::InvalidApiKey) ||
|
16
|
+
Geocoder.log(:warn, "Melissa service error: invalid API key.")
|
17
|
+
end
|
18
|
+
|
19
|
+
return doc["Records"]
|
20
|
+
end
|
21
|
+
|
22
|
+
private # ---------------------------------------------------------------
|
23
|
+
|
24
|
+
def base_query_url(query)
|
25
|
+
"#{protocol}://address.melissadata.net/v3/WEB/GlobalAddress/doGlobalAddress?"
|
26
|
+
end
|
27
|
+
|
28
|
+
def query_url_params(query)
|
29
|
+
params = {
|
30
|
+
id: configuration.api_key,
|
31
|
+
format: "JSON",
|
32
|
+
a1: query.sanitized_text,
|
33
|
+
loc: query.options[:city],
|
34
|
+
admarea: query.options[:state],
|
35
|
+
postal: query.options[:postal],
|
36
|
+
ctry: query.options[:country]
|
37
|
+
}
|
38
|
+
params.merge(super)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|