geocoder 1.5.0 → 1.6.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 +5 -5
- data/CHANGELOG.md +29 -2
- data/LICENSE +1 -1
- data/README.md +15 -17
- data/bin/console +7 -0
- data/examples/autoexpire_cache_redis.rb +2 -0
- data/lib/easting_northing.rb +171 -0
- data/lib/geocoder/calculations.rb +1 -1
- data/lib/geocoder/ip_address.rb +13 -0
- data/lib/geocoder/lookup.rb +8 -4
- data/lib/geocoder/lookups/baidu_ip.rb +1 -1
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +13 -0
- data/lib/geocoder/lookups/base.rb +7 -2
- data/lib/geocoder/lookups/bing.rb +2 -1
- data/lib/geocoder/lookups/esri.rb +38 -13
- data/lib/geocoder/lookups/freegeoip.rb +7 -7
- data/lib/geocoder/lookups/here.rb +28 -22
- data/lib/geocoder/lookups/ip2location.rb +7 -14
- data/lib/geocoder/lookups/ipapi_com.rb +2 -1
- data/lib/geocoder/lookups/ipdata_co.rb +5 -4
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +2 -11
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/ipstack.rb +2 -2
- data/lib/geocoder/lookups/maxmind.rb +2 -2
- data/lib/geocoder/lookups/maxmind_geoip2.rb +4 -7
- data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/lib/geocoder/lookups/osmnames.rb +57 -0
- data/lib/geocoder/lookups/pelias.rb +2 -3
- data/lib/geocoder/lookups/pickpoint.rb +1 -1
- data/lib/geocoder/lookups/pointpin.rb +3 -3
- data/lib/geocoder/lookups/smarty_streets.rb +13 -3
- data/lib/geocoder/lookups/telize.rb +2 -2
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +2 -2
- data/lib/geocoder/query.rb +14 -0
- data/lib/geocoder/railtie.rb +1 -1
- 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/smarty_streets.rb +48 -18
- data/lib/geocoder/results/tencent.rb +72 -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/stores/active_record.rb +1 -1
- data/lib/geocoder/version.rb +1 -1
- data/lib/hash_recursive_merge.rb +1 -2
- data/lib/maxmind_database.rb +3 -3
- metadata +18 -13
- data/lib/geocoder/lookups/geocoder_us.rb +0 -51
- data/lib/geocoder/lookups/mapzen.rb +0 -15
- data/lib/geocoder/results/geocoder_us.rb +0 -39
- data/lib/geocoder/results/mapzen.rb +0 -5
@@ -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
|
@@ -24,12 +24,11 @@ module Geocoder::Lookup
|
|
24
24
|
|
25
25
|
def query_url_params(query)
|
26
26
|
params = {
|
27
|
-
api_key: configuration.api_key
|
28
|
-
size: 1
|
27
|
+
api_key: configuration.api_key
|
29
28
|
}.merge(super)
|
30
29
|
|
31
30
|
if query.reverse_geocode?
|
32
|
-
lat,lon = query.coordinates
|
31
|
+
lat, lon = query.coordinates
|
33
32
|
params[:'point.lat'] = lat
|
34
33
|
params[:'point.lon'] = lon
|
35
34
|
else
|
@@ -23,8 +23,8 @@ module Geocoder::Lookup
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def results(query)
|
26
|
-
# don't look up a loopback address, just return the stored result
|
27
|
-
return [] if query.
|
26
|
+
# don't look up a loopback or private address, just return the stored result
|
27
|
+
return [] if query.internal_ip_address?
|
28
28
|
doc = fetch_data(query)
|
29
29
|
if doc and doc.is_a?(Hash)
|
30
30
|
if !data_contains_error?(doc)
|
@@ -42,7 +42,7 @@ module Geocoder::Lookup
|
|
42
42
|
raise_error(Geocoder::Error) || Geocoder.log(:warn, "Pointpin server error")
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
return []
|
47
47
|
end
|
48
48
|
|
@@ -8,7 +8,7 @@ module Geocoder::Lookup
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def required_api_key_parts
|
11
|
-
%w(
|
11
|
+
%w(auth-id auth-token)
|
12
12
|
end
|
13
13
|
|
14
14
|
# required by API as of 26 March 2015
|
@@ -19,7 +19,9 @@ module Geocoder::Lookup
|
|
19
19
|
private # ---------------------------------------------------------------
|
20
20
|
|
21
21
|
def base_query_url(query)
|
22
|
-
if
|
22
|
+
if international?(query)
|
23
|
+
"#{protocol}://international-street.api.smartystreets.com/verify?"
|
24
|
+
elsif zipcode_only?(query)
|
23
25
|
"#{protocol}://us-zipcode.api.smartystreets.com/lookup?"
|
24
26
|
else
|
25
27
|
"#{protocol}://us-street.api.smartystreets.com/street-address?"
|
@@ -30,9 +32,17 @@ module Geocoder::Lookup
|
|
30
32
|
!query.text.is_a?(Array) and query.to_s.strip =~ /\A\d{5}(-\d{4})?\Z/
|
31
33
|
end
|
32
34
|
|
35
|
+
def international?(query)
|
36
|
+
!query.options[:country].nil?
|
37
|
+
end
|
38
|
+
|
33
39
|
def query_url_params(query)
|
34
40
|
params = {}
|
35
|
-
if
|
41
|
+
if international?(query)
|
42
|
+
params[:freeform] = query.sanitized_text
|
43
|
+
params[:country] = query.options[:country]
|
44
|
+
params[:geocode] = true
|
45
|
+
elsif zipcode_only?(query)
|
36
46
|
params[:zipcode] = query.sanitized_text
|
37
47
|
else
|
38
48
|
params[:street] = query.sanitized_text
|
@@ -34,8 +34,8 @@ module Geocoder::Lookup
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def results(query)
|
37
|
-
# don't look up a loopback address, just return the stored result
|
38
|
-
return [reserved_result(query.text)] if query.
|
37
|
+
# don't look up a loopback or private address, just return the stored result
|
38
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
39
39
|
if (doc = fetch_data(query)).nil? or doc['code'] == 401 or empty_result?(doc)
|
40
40
|
[]
|
41
41
|
else
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/tencent"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Tencent < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Tencent"
|
9
|
+
end
|
10
|
+
|
11
|
+
def required_api_key_parts
|
12
|
+
["key"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def supported_protocols
|
16
|
+
[:https]
|
17
|
+
end
|
18
|
+
|
19
|
+
private # ---------------------------------------------------------------
|
20
|
+
|
21
|
+
def base_query_url(query)
|
22
|
+
"#{protocol}://apis.map.qq.com/ws/geocoder/v1/?"
|
23
|
+
end
|
24
|
+
|
25
|
+
def content_key
|
26
|
+
'result'
|
27
|
+
end
|
28
|
+
|
29
|
+
def results(query, reverse = false)
|
30
|
+
return [] unless doc = fetch_data(query)
|
31
|
+
case doc['status']
|
32
|
+
when 0
|
33
|
+
return [doc[content_key]]
|
34
|
+
when 311
|
35
|
+
raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
|
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
|
+
end
|
47
|
+
return []
|
48
|
+
end
|
49
|
+
|
50
|
+
def query_url_params(query)
|
51
|
+
{
|
52
|
+
(query.reverse_geocode? ? :location : :address) => query.sanitized_text,
|
53
|
+
:key => configuration.api_key,
|
54
|
+
:output => "json"
|
55
|
+
}.merge(super)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
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
|
@@ -50,8 +50,8 @@ module Geocoder::Lookup
|
|
50
50
|
params = {
|
51
51
|
:geocode => q,
|
52
52
|
:format => "json",
|
53
|
-
:
|
54
|
-
:
|
53
|
+
:lang => "#{query.language || configuration.language}", # supports ru, uk, be, default -> ru
|
54
|
+
:apikey => configuration.api_key
|
55
55
|
}
|
56
56
|
unless (bounds = query.options[:bounds]).nil?
|
57
57
|
params[:bbox] = bounds.map{ |point| "%f,%f" % point }.join('~')
|
data/lib/geocoder/query.rb
CHANGED
@@ -66,6 +66,13 @@ module Geocoder
|
|
66
66
|
IpAddress.new(text).valid? rescue false
|
67
67
|
end
|
68
68
|
|
69
|
+
##
|
70
|
+
# Is the Query text a loopback or private IP address?
|
71
|
+
#
|
72
|
+
def internal_ip_address?
|
73
|
+
ip_address? && IpAddress.new(text).internal?
|
74
|
+
end
|
75
|
+
|
69
76
|
##
|
70
77
|
# Is the Query text a loopback IP address?
|
71
78
|
#
|
@@ -73,6 +80,13 @@ module Geocoder
|
|
73
80
|
ip_address? && IpAddress.new(text).loopback?
|
74
81
|
end
|
75
82
|
|
83
|
+
##
|
84
|
+
# Is the Query text a private IP address?
|
85
|
+
#
|
86
|
+
def private_ip_address?
|
87
|
+
ip_address? && IpAddress.new(text).private?
|
88
|
+
end
|
89
|
+
|
76
90
|
##
|
77
91
|
# Does the given string look like latitude/longitude coordinates?
|
78
92
|
#
|
data/lib/geocoder/railtie.rb
CHANGED
@@ -4,7 +4,7 @@ module Geocoder
|
|
4
4
|
if defined? Rails::Railtie
|
5
5
|
require 'rails'
|
6
6
|
class Railtie < Rails::Railtie
|
7
|
-
initializer 'geocoder.insert_into_active_record' do
|
7
|
+
initializer 'geocoder.insert_into_active_record', before: :load_config_initializers do
|
8
8
|
ActiveSupport.on_load :active_record do
|
9
9
|
Geocoder::Railtie.insert
|
10
10
|
end
|
@@ -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
|