geocoder 1.5.1 → 1.6.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 +26 -0
- data/LICENSE +1 -1
- data/README.md +8 -10
- data/bin/console +13 -0
- data/examples/autoexpire_cache_redis.rb +2 -0
- data/lib/easting_northing.rb +171 -0
- data/lib/geocoder/ip_address.rb +2 -1
- data/lib/geocoder/lookup.rb +7 -3
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +13 -0
- data/lib/geocoder/lookups/base.rb +2 -0
- data/lib/geocoder/lookups/esri.rb +2 -0
- data/lib/geocoder/lookups/freegeoip.rb +4 -4
- data/lib/geocoder/lookups/here.rb +7 -16
- data/lib/geocoder/lookups/ip2location.rb +5 -13
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/latlon.rb +1 -2
- data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/lib/geocoder/lookups/osmnames.rb +57 -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/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +3 -4
- data/lib/geocoder/results/baidu.rb +0 -4
- data/lib/geocoder/results/ban_data_gouv_fr.rb +1 -1
- data/lib/geocoder/results/here.rb +4 -1
- data/lib/geocoder/results/ipgeolocation.rb +59 -0
- data/lib/geocoder/results/ipregistry.rb +308 -0
- data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
- data/lib/geocoder/results/osmnames.rb +56 -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/version.rb +1 -1
- data/lib/hash_recursive_merge.rb +1 -2
- data/lib/maxmind_database.rb +3 -3
- metadata +19 -15
- data/lib/geocoder/lookups/geocoder_us.rb +0 -51
- data/lib/geocoder/results/geocoder_us.rb +0 -39
|
@@ -19,11 +19,11 @@ module Geocoder::Lookup
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def query_url_params(query)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
params = super
|
|
23
|
+
if configuration.has_key?(:package)
|
|
24
|
+
params.merge!(package: configuration[:package])
|
|
25
|
+
end
|
|
26
|
+
params
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def results(query)
|
|
@@ -63,13 +63,5 @@ module Geocoder::Lookup
|
|
|
63
63
|
}
|
|
64
64
|
end
|
|
65
65
|
|
|
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
66
|
end
|
|
75
67
|
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,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
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require "geocoder/results/nationaal_georegister_nl"
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class NationaalGeoregisterNl < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
'Nationaal Georegister Nederland'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private # ---------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
def cache_key(query)
|
|
14
|
+
base_query_url(query) + hash_to_query(query_url_params(query))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def base_query_url(query)
|
|
18
|
+
"#{protocol}://geodata.nationaalgeoregister.nl/locatieserver/v3/free?"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def valid_response?(response)
|
|
22
|
+
json = parse_json(response.body)
|
|
23
|
+
super(response) if json
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def results(query)
|
|
27
|
+
return [] unless doc = fetch_data(query)
|
|
28
|
+
return doc['response']['docs']
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def query_url_params(query)
|
|
32
|
+
{
|
|
33
|
+
fl: '*',
|
|
34
|
+
q: query.text
|
|
35
|
+
}.merge(super)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'cgi'
|
|
2
|
+
require 'geocoder/lookups/base'
|
|
3
|
+
require 'geocoder/results/osmnames'
|
|
4
|
+
|
|
5
|
+
module Geocoder::Lookup
|
|
6
|
+
class Osmnames < Base
|
|
7
|
+
|
|
8
|
+
def name
|
|
9
|
+
'OSM Names'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def required_api_key_parts
|
|
13
|
+
configuration[:host] ? [] : ['key']
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def supported_protocols
|
|
17
|
+
[:https]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def base_query_url(query)
|
|
23
|
+
"#{base_url(query)}/#{params_url(query)}.js?"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def base_url(query)
|
|
27
|
+
host = configuration[:host] || 'geocoder.tilehosting.com'
|
|
28
|
+
"#{protocol}://#{host}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def params_url(query)
|
|
32
|
+
method, args = 'q', CGI.escape(query.sanitized_text)
|
|
33
|
+
method, args = 'r', query.coordinates.join('/') if query.reverse_geocode?
|
|
34
|
+
"#{country_limited(query)}#{method}/#{args}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def results(query)
|
|
38
|
+
return [] unless doc = fetch_data(query)
|
|
39
|
+
if (error = doc['message'])
|
|
40
|
+
raise_error(Geocoder::InvalidRequest, error) ||
|
|
41
|
+
Geocoder.log(:warn, "OSMNames Geocoding API error: #{error}")
|
|
42
|
+
else
|
|
43
|
+
return doc['results']
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def query_url_params(query)
|
|
48
|
+
{
|
|
49
|
+
key: configuration.api_key
|
|
50
|
+
}.merge(super)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def country_limited(query)
|
|
54
|
+
"#{query.options[:country_code].downcase}/" if query.options[:country_code] && !query.reverse_geocode?
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -57,7 +57,12 @@ module Geocoder::Lookup
|
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def results(query)
|
|
60
|
-
fetch_data(query) || []
|
|
60
|
+
doc = fetch_data(query) || []
|
|
61
|
+
if doc.is_a?(Hash) and doc.key?('status') # implies there's an error
|
|
62
|
+
return []
|
|
63
|
+
else
|
|
64
|
+
return doc
|
|
65
|
+
end
|
|
61
66
|
end
|
|
62
67
|
end
|
|
63
68
|
end
|
|
@@ -16,7 +16,7 @@ module Geocoder::Lookup
|
|
|
16
16
|
if configuration[:host]
|
|
17
17
|
"#{protocol}://#{configuration[:host]}/location/#{query.sanitized_text}"
|
|
18
18
|
else
|
|
19
|
-
"#{protocol}://telize-v1.p.
|
|
19
|
+
"#{protocol}://telize-v1.p.rapidapi.com/location/#{query.sanitized_text}?rapidapi-key=#{api_key}"
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -31,18 +31,18 @@ module Geocoder::Lookup
|
|
|
31
31
|
case doc['status']
|
|
32
32
|
when 0
|
|
33
33
|
return [doc[content_key]]
|
|
34
|
-
when 199
|
|
35
|
-
raise error(Geocoder::InvalidApiKey, "invalid api key") ||
|
|
36
|
-
Geocoder.log(:warn, "#{name} Geocoding API error: key is not enabled for web service usage.")
|
|
37
|
-
when 311
|
|
38
|
-
raise_error(Geocoder::RequestDenied, "request denied") ||
|
|
39
|
-
Geocoder.log(:warn, "#{name} Geocoding API error: request denied.")
|
|
40
|
-
when 310, 306
|
|
41
|
-
raise_error(Geocoder::InvalidRequest, "invalid request.") ||
|
|
42
|
-
Geocoder.log(:warn, "#{name} Geocoding API error: invalid request.")
|
|
43
34
|
when 311
|
|
44
35
|
raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
|
|
45
36
|
Geocoder.log(:warn, "#{name} Geocoding API error: invalid api key.")
|
|
37
|
+
when 310
|
|
38
|
+
raise_error(Geocoder::InvalidRequest, "invalid request.") ||
|
|
39
|
+
Geocoder.log(:warn, "#{name} Geocoding API error: invalid request, invalid parameters.")
|
|
40
|
+
when 306
|
|
41
|
+
raise_error(Geocoder::InvalidRequest, "invalid request.") ||
|
|
42
|
+
Geocoder.log(:warn, "#{name} Geocoding API error: invalid request, check response for more info.")
|
|
43
|
+
when 110
|
|
44
|
+
raise_error(Geocoder::RequestDenied, "request denied.") ||
|
|
45
|
+
Geocoder.log(:warn, "#{name} Geocoding API error: request source is not authorized.")
|
|
46
46
|
end
|
|
47
47
|
return []
|
|
48
48
|
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/uk_ordnance_survey_names'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class UkOrdnanceSurveyNames < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
'Ordance Survey Names'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def supported_protocols
|
|
12
|
+
[:https]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def base_query_url(query)
|
|
16
|
+
"#{protocol}://api.ordnancesurvey.co.uk/opennames/v1/find?"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def required_api_key_parts
|
|
20
|
+
["key"]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def query_url(query)
|
|
24
|
+
base_query_url(query) + url_query_string(query)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private # -------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
def results(query)
|
|
30
|
+
return [] unless doc = fetch_data(query)
|
|
31
|
+
return [] if doc['header']['totalresults'].zero?
|
|
32
|
+
return doc['results'].map { |r| r['GAZETTEER_ENTRY'] }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def query_url_params(query)
|
|
36
|
+
{
|
|
37
|
+
query: query.sanitized_text,
|
|
38
|
+
key: configuration.api_key,
|
|
39
|
+
fq: filter
|
|
40
|
+
}.merge(super)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def local_types
|
|
44
|
+
%w[
|
|
45
|
+
City
|
|
46
|
+
Hamlet
|
|
47
|
+
Other_Settlement
|
|
48
|
+
Town
|
|
49
|
+
Village
|
|
50
|
+
Postcode
|
|
51
|
+
]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def filter
|
|
55
|
+
local_types.map { |t| "local_type:#{t}" }.join(' ')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -33,8 +33,7 @@ module Geocoder::Lookup
|
|
|
33
33
|
return []
|
|
34
34
|
end
|
|
35
35
|
if doc = doc['response']['GeoObjectCollection']
|
|
36
|
-
|
|
37
|
-
return meta['found'].to_i > 0 ? doc['featureMember'] : []
|
|
36
|
+
return doc['featureMember'].to_a
|
|
38
37
|
else
|
|
39
38
|
Geocoder.log(:warn, "Yandex Geocoding API error: unexpected response format.")
|
|
40
39
|
return []
|
|
@@ -50,8 +49,8 @@ module Geocoder::Lookup
|
|
|
50
49
|
params = {
|
|
51
50
|
:geocode => q,
|
|
52
51
|
:format => "json",
|
|
53
|
-
:
|
|
54
|
-
:
|
|
52
|
+
:lang => "#{query.language || configuration.language}", # supports ru, uk, be, default -> ru
|
|
53
|
+
:apikey => configuration.api_key
|
|
55
54
|
}
|
|
56
55
|
unless (bounds = query.options[:bounds]).nil?
|
|
57
56
|
params[:bbox] = bounds.map{ |point| "%f,%f" % point }.join('~')
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'geocoder/results/base'
|
|
2
|
+
|
|
3
|
+
module Geocoder::Result
|
|
4
|
+
class Ipgeolocation < Base
|
|
5
|
+
|
|
6
|
+
def coordinates
|
|
7
|
+
[@data['latitude'].to_f, @data['longitude'].to_f]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def address(format = :full)
|
|
11
|
+
"#{city}, #{state} #{postal_code}, #{country_name}".sub(/^[ ,]*/, "")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def state
|
|
15
|
+
@data['state_prov']
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def state_code
|
|
19
|
+
@data['state_prov']
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def country
|
|
23
|
+
@data['country_name']
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def country_code
|
|
27
|
+
@data['country_code2']
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def postal_code
|
|
31
|
+
@data['zipcode']
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.response_attributes
|
|
35
|
+
[
|
|
36
|
+
['ip', ''],
|
|
37
|
+
['hostname', ''],
|
|
38
|
+
['continent_code', ''],
|
|
39
|
+
['continent_name', ''],
|
|
40
|
+
['country_code2', ''],
|
|
41
|
+
['country_code3', ''],
|
|
42
|
+
['country_name', ''],
|
|
43
|
+
['country_capital',''],
|
|
44
|
+
['district',''],
|
|
45
|
+
['state_prov',''],
|
|
46
|
+
['city', ''],
|
|
47
|
+
['zipcode', ''],
|
|
48
|
+
['time_zone', {}],
|
|
49
|
+
['currency', {}]
|
|
50
|
+
]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
response_attributes.each do |attr, default|
|
|
54
|
+
define_method attr do
|
|
55
|
+
@data[attr] || default
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|