geocoder 1.5.1 → 1.7.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +65 -0
- data/LICENSE +1 -1
- data/README.md +333 -238
- data/bin/console +13 -0
- data/lib/easting_northing.rb +171 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +7 -1
- data/lib/geocoder/cache.rb +16 -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 +11 -4
- data/lib/geocoder/configuration_hash.rb +4 -4
- data/lib/geocoder/ip_address.rb +8 -1
- data/lib/geocoder/lookup.rb +21 -3
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/amazon_location_service.rb +54 -0
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +14 -1
- data/lib/geocoder/lookups/base.rb +10 -2
- data/lib/geocoder/lookups/bing.rb +1 -1
- data/lib/geocoder/lookups/esri.rb +6 -0
- data/lib/geocoder/lookups/freegeoip.rb +4 -4
- data/lib/geocoder/lookups/geoapify.rb +72 -0
- data/lib/geocoder/lookups/geocodio.rb +1 -1
- data/lib/geocoder/lookups/geoip2.rb +4 -0
- data/lib/geocoder/lookups/google.rb +7 -2
- data/lib/geocoder/lookups/google_places_details.rb +8 -14
- data/lib/geocoder/lookups/google_places_search.rb +28 -2
- data/lib/geocoder/lookups/google_premier.rb +4 -0
- data/lib/geocoder/lookups/here.rb +7 -16
- data/lib/geocoder/lookups/ip2location.rb +10 -14
- data/lib/geocoder/lookups/ipdata_co.rb +1 -1
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipqualityscore.rb +50 -0
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/latlon.rb +1 -2
- data/lib/geocoder/lookups/maxmind_local.rb +7 -1
- data/lib/geocoder/lookups/melissa_street.rb +41 -0
- data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/lib/geocoder/lookups/osmnames.rb +57 -0
- data/lib/geocoder/lookups/photon.rb +89 -0
- data/lib/geocoder/lookups/pickpoint.rb +1 -1
- data/lib/geocoder/lookups/smarty_streets.rb +6 -1
- data/lib/geocoder/lookups/telize.rb +1 -1
- data/lib/geocoder/lookups/tencent.rb +9 -9
- data/lib/geocoder/lookups/test.rb +4 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +3 -4
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/amazon_location_service.rb +57 -0
- data/lib/geocoder/results/baidu.rb +0 -4
- data/lib/geocoder/results/ban_data_gouv_fr.rb +27 -2
- data/lib/geocoder/results/db_ip_com.rb +1 -1
- data/lib/geocoder/results/esri.rb +5 -2
- data/lib/geocoder/results/geoapify.rb +179 -0
- data/lib/geocoder/results/here.rb +4 -1
- data/lib/geocoder/results/ipgeolocation.rb +59 -0
- data/lib/geocoder/results/ipqualityscore.rb +54 -0
- data/lib/geocoder/results/ipregistry.rb +304 -0
- data/lib/geocoder/results/mapbox.rb +10 -4
- data/lib/geocoder/results/melissa_street.rb +46 -0
- data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
- data/lib/geocoder/results/nominatim.rb +27 -15
- data/lib/geocoder/results/osmnames.rb +56 -0
- data/lib/geocoder/results/photon.rb +119 -0
- data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/results/yandex.rb +217 -59
- data/lib/geocoder/sql.rb +4 -4
- data/lib/geocoder/util.rb +29 -0
- data/lib/geocoder/version.rb +1 -1
- data/lib/maxmind_database.rb +3 -3
- metadata +35 -18
- data/examples/autoexpire_cache_dalli.rb +0 -62
- data/examples/autoexpire_cache_redis.rb +0 -28
- data/lib/geocoder/lookups/geocoder_us.rb +0 -51
- data/lib/geocoder/results/geocoder_us.rb +0 -39
- data/lib/hash_recursive_merge.rb +0 -74
@@ -22,7 +22,7 @@ module Geocoder::Lookup
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def any_result?(doc)
|
25
|
-
doc['features'].any?
|
25
|
+
doc['features'] and doc['features'].any?
|
26
26
|
end
|
27
27
|
|
28
28
|
def results(query)
|
@@ -86,6 +86,12 @@ module Geocoder::Lookup
|
|
86
86
|
unless (citycode = query.options[:citycode]).nil? || !code_param_is_valid?(citycode)
|
87
87
|
params[:citycode] = citycode.to_s
|
88
88
|
end
|
89
|
+
unless (lat = query.options[:lat]).nil? || !latitude_is_valid?(lat)
|
90
|
+
params[:lat] = lat
|
91
|
+
end
|
92
|
+
unless (lon = query.options[:lon]).nil? || !longitude_is_valid?(lon)
|
93
|
+
params[:lon] = lon
|
94
|
+
end
|
89
95
|
params
|
90
96
|
end
|
91
97
|
|
@@ -126,5 +132,12 @@ module Geocoder::Lookup
|
|
126
132
|
(1..99999).include?(param.to_i)
|
127
133
|
end
|
128
134
|
|
135
|
+
def latitude_is_valid?(param)
|
136
|
+
param.to_f <= 90 && param.to_f >= -90
|
137
|
+
end
|
138
|
+
|
139
|
+
def longitude_is_valid?(param)
|
140
|
+
param.to_f <= 180 && param.to_f >= -180
|
141
|
+
end
|
129
142
|
end
|
130
143
|
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
|
@@ -197,6 +203,8 @@ module Geocoder
|
|
197
203
|
raise_error(err) or Geocoder.log(:warn, "Geocoding API connection cannot be established.")
|
198
204
|
rescue Errno::ECONNREFUSED => err
|
199
205
|
raise_error(err) or Geocoder.log(:warn, "Geocoding API connection refused.")
|
206
|
+
rescue Geocoder::NetworkError => err
|
207
|
+
raise_error(err) or Geocoder.log(:warn, "Geocoding API connection is either unreacheable or reset by the peer")
|
200
208
|
rescue Timeout::Error => err
|
201
209
|
raise_error(err) or Geocoder.log(:warn, "Geocoding API not responding fast enough " +
|
202
210
|
"(use Geocoder.configure(:timeout => ...) to set limit).")
|
@@ -9,6 +9,10 @@ module Geocoder::Lookup
|
|
9
9
|
"Esri"
|
10
10
|
end
|
11
11
|
|
12
|
+
def supported_protocols
|
13
|
+
[:https]
|
14
|
+
end
|
15
|
+
|
12
16
|
private # ---------------------------------------------------------------
|
13
17
|
|
14
18
|
def base_query_url(query)
|
@@ -47,6 +51,8 @@ module Geocoder::Lookup
|
|
47
51
|
params[:forStorage] = for_storage_value
|
48
52
|
end
|
49
53
|
params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
|
54
|
+
params[:preferredLabelValues] = configuration[:preferred_label_values] if configuration[:preferred_label_values]
|
55
|
+
|
50
56
|
params.merge(super)
|
51
57
|
end
|
52
58
|
|
@@ -10,7 +10,7 @@ module Geocoder::Lookup
|
|
10
10
|
|
11
11
|
def supported_protocols
|
12
12
|
if configuration[:host]
|
13
|
-
[:
|
13
|
+
[:https]
|
14
14
|
else
|
15
15
|
# use https for default host
|
16
16
|
[:https]
|
@@ -44,8 +44,8 @@ module Geocoder::Lookup
|
|
44
44
|
"city" => "",
|
45
45
|
"region_code" => "",
|
46
46
|
"region_name" => "",
|
47
|
-
"
|
48
|
-
"
|
47
|
+
"metro_code" => "",
|
48
|
+
"zip_code" => "",
|
49
49
|
"latitude" => "0",
|
50
50
|
"longitude" => "0",
|
51
51
|
"country_name" => "Reserved",
|
@@ -54,7 +54,7 @@ module Geocoder::Lookup
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def host
|
57
|
-
configuration[:host] || "freegeoip.
|
57
|
+
configuration[:host] || "freegeoip.app"
|
58
58
|
end
|
59
59
|
end
|
60
60
|
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
|
@@ -44,10 +44,15 @@ module Geocoder::Lookup
|
|
44
44
|
super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
|
45
45
|
end
|
46
46
|
|
47
|
+
def result_root_attr
|
48
|
+
'results'
|
49
|
+
end
|
50
|
+
|
47
51
|
def results(query)
|
48
52
|
return [] unless doc = fetch_data(query)
|
49
|
-
case doc['status']
|
50
|
-
|
53
|
+
case doc['status']
|
54
|
+
when "OK" # OK status implies >0 results
|
55
|
+
return doc[result_root_attr]
|
51
56
|
when "OVER_QUERY_LIMIT"
|
52
57
|
raise_error(Geocoder::OverQueryLimitError) ||
|
53
58
|
Geocoder.log(:warn, "#{name} API error: over query limit.")
|
@@ -22,21 +22,15 @@ module Geocoder
|
|
22
22
|
"#{protocol}://maps.googleapis.com/maps/api/place/details/json?"
|
23
23
|
end
|
24
24
|
|
25
|
+
def result_root_attr
|
26
|
+
'result'
|
27
|
+
end
|
28
|
+
|
25
29
|
def results(query)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
return [doc["result"]]
|
31
|
-
when "OVER_QUERY_LIMIT"
|
32
|
-
raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Google Places Details API error: over query limit.")
|
33
|
-
when "REQUEST_DENIED"
|
34
|
-
raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Google Places Details API error: request denied.")
|
35
|
-
when "INVALID_REQUEST"
|
36
|
-
raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, "Google Places Details API error: invalid request.")
|
37
|
-
end
|
38
|
-
|
39
|
-
[]
|
30
|
+
result = super(query)
|
31
|
+
return [result] unless result.is_a? Array
|
32
|
+
|
33
|
+
result
|
40
34
|
end
|
41
35
|
|
42
36
|
def query_url_google_params(query)
|
@@ -18,16 +18,42 @@ module Geocoder
|
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
+
def result_root_attr
|
22
|
+
'candidates'
|
23
|
+
end
|
24
|
+
|
21
25
|
def base_query_url(query)
|
22
|
-
"#{protocol}://maps.googleapis.com/maps/api/place/
|
26
|
+
"#{protocol}://maps.googleapis.com/maps/api/place/findplacefromtext/json?"
|
23
27
|
end
|
24
28
|
|
25
29
|
def query_url_google_params(query)
|
26
30
|
{
|
27
|
-
|
31
|
+
input: query.text,
|
32
|
+
inputtype: 'textquery',
|
33
|
+
fields: fields(query),
|
28
34
|
language: query.language || configuration.language
|
29
35
|
}
|
30
36
|
end
|
37
|
+
|
38
|
+
def fields(query)
|
39
|
+
query_fields = query.options[:fields]
|
40
|
+
return format_fields(query_fields) if query_fields
|
41
|
+
|
42
|
+
default_fields
|
43
|
+
end
|
44
|
+
|
45
|
+
def default_fields
|
46
|
+
legacy = %w[id reference]
|
47
|
+
basic = %w[business_status formatted_address geometry icon name
|
48
|
+
photos place_id plus_code types]
|
49
|
+
contact = %w[opening_hours]
|
50
|
+
atmosphere = %W[price_level rating user_ratings_total]
|
51
|
+
format_fields(legacy, basic, contact, atmosphere)
|
52
|
+
end
|
53
|
+
|
54
|
+
def format_fields(*fields)
|
55
|
+
fields.flatten.join(',')
|
56
|
+
end
|
31
57
|
end
|
32
58
|
end
|
33
59
|
end
|
@@ -21,6 +21,10 @@ module Geocoder::Lookup
|
|
21
21
|
|
22
22
|
private # ---------------------------------------------------------------
|
23
23
|
|
24
|
+
def result_root_attr
|
25
|
+
'results'
|
26
|
+
end
|
27
|
+
|
24
28
|
def cache_key(query)
|
25
29
|
"#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + hash_to_query(cache_key_params(query))
|
26
30
|
end
|
@@ -9,13 +9,17 @@ module Geocoder::Lookup
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def required_api_key_parts
|
12
|
-
[
|
12
|
+
['api_key']
|
13
|
+
end
|
14
|
+
|
15
|
+
def supported_protocols
|
16
|
+
[:https]
|
13
17
|
end
|
14
18
|
|
15
19
|
private # ---------------------------------------------------------------
|
16
20
|
|
17
21
|
def base_query_url(query)
|
18
|
-
"#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.
|
22
|
+
"#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.ls.hereapi.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
|
19
23
|
end
|
20
24
|
|
21
25
|
def results(query)
|
@@ -31,8 +35,7 @@ module Geocoder::Lookup
|
|
31
35
|
def query_url_here_options(query, reverse_geocode)
|
32
36
|
options = {
|
33
37
|
gen: 9,
|
34
|
-
|
35
|
-
app_code: api_code,
|
38
|
+
apikey: configuration.api_key,
|
36
39
|
language: (query.language || configuration.language)
|
37
40
|
}
|
38
41
|
if reverse_geocode
|
@@ -61,17 +64,5 @@ module Geocoder::Lookup
|
|
61
64
|
)
|
62
65
|
end
|
63
66
|
end
|
64
|
-
|
65
|
-
def api_key
|
66
|
-
if (a = configuration.api_key)
|
67
|
-
return a.first if a.is_a?(Array)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def api_code
|
72
|
-
if (a = configuration.api_key)
|
73
|
-
return a.last if a.is_a?(Array)
|
74
|
-
end
|
75
|
-
end
|
76
67
|
end
|
77
68
|
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
|
-
key: configuration.api_key
|
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)
|
@@ -63,13 +67,5 @@ module Geocoder::Lookup
|
|
63
67
|
}
|
64
68
|
end
|
65
69
|
|
66
|
-
def query_url_params(query)
|
67
|
-
params = super
|
68
|
-
if configuration.has_key?(:package)
|
69
|
-
params.merge!(package: configuration[:package])
|
70
|
-
end
|
71
|
-
params
|
72
|
-
end
|
73
|
-
|
74
70
|
end
|
75
71
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/ipgeolocation'
|
3
|
+
|
4
|
+
|
5
|
+
module Geocoder::Lookup
|
6
|
+
class Ipgeolocation < Base
|
7
|
+
|
8
|
+
ERROR_CODES = {
|
9
|
+
400 => Geocoder::RequestDenied, # subscription is paused
|
10
|
+
401 => Geocoder::InvalidApiKey, # missing/invalid API key
|
11
|
+
403 => Geocoder::InvalidRequest, # invalid IP address
|
12
|
+
404 => Geocoder::InvalidRequest, # not found
|
13
|
+
423 => Geocoder::InvalidRequest # bogon/reserved IP address
|
14
|
+
}
|
15
|
+
ERROR_CODES.default = Geocoder::Error
|
16
|
+
|
17
|
+
def name
|
18
|
+
"Ipgeolocation"
|
19
|
+
end
|
20
|
+
|
21
|
+
def supported_protocols
|
22
|
+
[:https]
|
23
|
+
end
|
24
|
+
|
25
|
+
private # ----------------------------------------------------------------
|
26
|
+
|
27
|
+
def base_query_url(query)
|
28
|
+
"#{protocol}://api.ipgeolocation.io/ipgeo?"
|
29
|
+
end
|
30
|
+
def query_url_params(query)
|
31
|
+
{
|
32
|
+
ip: query.sanitized_text,
|
33
|
+
apiKey: configuration.api_key
|
34
|
+
}.merge(super)
|
35
|
+
end
|
36
|
+
|
37
|
+
def results(query)
|
38
|
+
# don't look up a loopback or private address, just return the stored result
|
39
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
40
|
+
[fetch_data(query)]
|
41
|
+
end
|
42
|
+
|
43
|
+
def reserved_result(ip)
|
44
|
+
{
|
45
|
+
"ip" => ip,
|
46
|
+
"country_name" => "Reserved",
|
47
|
+
"country_code2" => "RD"
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -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,68 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/ipregistry'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Ipregistry < Base
|
6
|
+
|
7
|
+
ERROR_CODES = {
|
8
|
+
400 => Geocoder::InvalidRequest,
|
9
|
+
401 => Geocoder::InvalidRequest,
|
10
|
+
402 => Geocoder::OverQueryLimitError,
|
11
|
+
403 => Geocoder::InvalidApiKey,
|
12
|
+
451 => Geocoder::RequestDenied,
|
13
|
+
500 => Geocoder::Error
|
14
|
+
}
|
15
|
+
ERROR_CODES.default = Geocoder::Error
|
16
|
+
|
17
|
+
def name
|
18
|
+
"Ipregistry"
|
19
|
+
end
|
20
|
+
|
21
|
+
def supported_protocols
|
22
|
+
[:https, :http]
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def base_query_url(query)
|
28
|
+
"#{protocol}://#{host}/#{query.sanitized_text}?"
|
29
|
+
end
|
30
|
+
|
31
|
+
def cache_key(query)
|
32
|
+
query_url(query)
|
33
|
+
end
|
34
|
+
|
35
|
+
def host
|
36
|
+
configuration[:host] || "api.ipregistry.co"
|
37
|
+
end
|
38
|
+
|
39
|
+
def query_url_params(query)
|
40
|
+
{
|
41
|
+
key: configuration.api_key
|
42
|
+
}.merge(super)
|
43
|
+
end
|
44
|
+
|
45
|
+
def results(query)
|
46
|
+
# don't look up a loopback or private address, just return the stored result
|
47
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
48
|
+
|
49
|
+
return [] unless (doc = fetch_data(query))
|
50
|
+
|
51
|
+
if (error = doc['error'])
|
52
|
+
code = error['code']
|
53
|
+
msg = error['message']
|
54
|
+
raise_error(ERROR_CODES[code], msg ) || Geocoder.log(:warn, "Ipregistry API error: #{msg}")
|
55
|
+
return []
|
56
|
+
end
|
57
|
+
[doc]
|
58
|
+
end
|
59
|
+
|
60
|
+
def reserved_result(ip)
|
61
|
+
{
|
62
|
+
"ip" => ip,
|
63
|
+
"country_name" => "Reserved",
|
64
|
+
"country_code" => "RD"
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -25,8 +25,7 @@ module Geocoder::Lookup
|
|
25
25
|
# The API returned a 404 response, which indicates no results found
|
26
26
|
elsif doc['error']['type'] == 'api_error'
|
27
27
|
[]
|
28
|
-
elsif
|
29
|
-
doc['error']['type'] == 'authentication_error'
|
28
|
+
elsif doc['error']['type'] == 'authentication_error'
|
30
29
|
raise_error(Geocoder::InvalidApiKey) ||
|
31
30
|
Geocoder.log(:warn, "LatLon.io service error: invalid API key.")
|
32
31
|
else
|
@@ -30,7 +30,13 @@ module Geocoder::Lookup
|
|
30
30
|
def results(query)
|
31
31
|
if configuration[:file]
|
32
32
|
geoip_class = RUBY_PLATFORM == "java" ? JGeoIP : GeoIP
|
33
|
-
|
33
|
+
geoip_instance = geoip_class.new(configuration[:file])
|
34
|
+
result =
|
35
|
+
if configuration[:package] == :country
|
36
|
+
geoip_instance.country(query.to_s)
|
37
|
+
else
|
38
|
+
geoip_instance.city(query.to_s)
|
39
|
+
end
|
34
40
|
result.nil? ? [] : [encode_hash(result.to_hash)]
|
35
41
|
elsif configuration[:package] == :city
|
36
42
|
addr = IPAddr.new(query.text).to_i
|
@@ -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
|