really-broken-geocoder 1.5.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/CHANGELOG.md +557 -0
- data/LICENSE +20 -0
- data/README.md +3 -0
- data/bin/geocode +5 -0
- data/examples/autoexpire_cache_dalli.rb +62 -0
- data/examples/autoexpire_cache_redis.rb +28 -0
- data/examples/cache_bypass.rb +48 -0
- data/examples/reverse_geocode_job.rb +40 -0
- data/lib/generators/geocoder/config/config_generator.rb +14 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +22 -0
- data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +30 -0
- data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +30 -0
- data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
- data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
- data/lib/generators/geocoder/migration_version.rb +15 -0
- data/lib/geocoder.rb +48 -0
- data/lib/geocoder/cache.rb +94 -0
- data/lib/geocoder/calculations.rb +420 -0
- data/lib/geocoder/cli.rb +121 -0
- data/lib/geocoder/configuration.rb +137 -0
- data/lib/geocoder/configuration_hash.rb +11 -0
- data/lib/geocoder/esri_token.rb +38 -0
- data/lib/geocoder/exceptions.rb +40 -0
- data/lib/geocoder/ip_address.rb +26 -0
- data/lib/geocoder/kernel_logger.rb +25 -0
- data/lib/geocoder/logger.rb +47 -0
- data/lib/geocoder/lookup.rb +118 -0
- data/lib/geocoder/lookups/amap.rb +63 -0
- data/lib/geocoder/lookups/baidu.rb +63 -0
- data/lib/geocoder/lookups/baidu_ip.rb +30 -0
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +130 -0
- data/lib/geocoder/lookups/base.rb +348 -0
- data/lib/geocoder/lookups/bing.rb +82 -0
- data/lib/geocoder/lookups/db_ip_com.rb +52 -0
- data/lib/geocoder/lookups/dstk.rb +22 -0
- data/lib/geocoder/lookups/esri.rb +95 -0
- data/lib/geocoder/lookups/freegeoip.rb +60 -0
- data/lib/geocoder/lookups/geocoder_ca.rb +53 -0
- data/lib/geocoder/lookups/geocoder_us.rb +51 -0
- data/lib/geocoder/lookups/geocodio.rb +42 -0
- data/lib/geocoder/lookups/geoip2.rb +45 -0
- data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
- data/lib/geocoder/lookups/google.rb +95 -0
- data/lib/geocoder/lookups/google_places_details.rb +50 -0
- data/lib/geocoder/lookups/google_places_search.rb +33 -0
- data/lib/geocoder/lookups/google_premier.rb +57 -0
- data/lib/geocoder/lookups/here.rb +77 -0
- data/lib/geocoder/lookups/ip2location.rb +75 -0
- data/lib/geocoder/lookups/ipapi_com.rb +82 -0
- data/lib/geocoder/lookups/ipdata_co.rb +62 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +44 -0
- data/lib/geocoder/lookups/ipstack.rb +63 -0
- data/lib/geocoder/lookups/latlon.rb +59 -0
- data/lib/geocoder/lookups/location_iq.rb +50 -0
- data/lib/geocoder/lookups/mapbox.rb +59 -0
- data/lib/geocoder/lookups/mapquest.rb +58 -0
- data/lib/geocoder/lookups/maxmind.rb +90 -0
- data/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
- data/lib/geocoder/lookups/maxmind_local.rb +65 -0
- data/lib/geocoder/lookups/nominatim.rb +64 -0
- data/lib/geocoder/lookups/opencagedata.rb +65 -0
- data/lib/geocoder/lookups/pelias.rb +63 -0
- data/lib/geocoder/lookups/pickpoint.rb +41 -0
- data/lib/geocoder/lookups/pointpin.rb +69 -0
- data/lib/geocoder/lookups/postcode_anywhere_uk.rb +50 -0
- data/lib/geocoder/lookups/postcodes_io.rb +31 -0
- data/lib/geocoder/lookups/smarty_streets.rb +63 -0
- data/lib/geocoder/lookups/telize.rb +75 -0
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/lookups/test.rb +44 -0
- data/lib/geocoder/lookups/yandex.rb +62 -0
- data/lib/geocoder/models/active_record.rb +51 -0
- data/lib/geocoder/models/base.rb +39 -0
- data/lib/geocoder/models/mongo_base.rb +62 -0
- data/lib/geocoder/models/mongo_mapper.rb +26 -0
- data/lib/geocoder/models/mongoid.rb +32 -0
- data/lib/geocoder/query.rb +125 -0
- data/lib/geocoder/railtie.rb +26 -0
- data/lib/geocoder/request.rb +114 -0
- data/lib/geocoder/results/amap.rb +87 -0
- data/lib/geocoder/results/baidu.rb +79 -0
- data/lib/geocoder/results/baidu_ip.rb +62 -0
- data/lib/geocoder/results/ban_data_gouv_fr.rb +257 -0
- data/lib/geocoder/results/base.rb +79 -0
- data/lib/geocoder/results/bing.rb +52 -0
- data/lib/geocoder/results/db_ip_com.rb +58 -0
- data/lib/geocoder/results/dstk.rb +6 -0
- data/lib/geocoder/results/esri.rb +75 -0
- data/lib/geocoder/results/freegeoip.rb +40 -0
- data/lib/geocoder/results/geocoder_ca.rb +60 -0
- data/lib/geocoder/results/geocoder_us.rb +39 -0
- data/lib/geocoder/results/geocodio.rb +78 -0
- data/lib/geocoder/results/geoip2.rb +76 -0
- data/lib/geocoder/results/geoportail_lu.rb +71 -0
- data/lib/geocoder/results/google.rb +150 -0
- data/lib/geocoder/results/google_places_details.rb +39 -0
- data/lib/geocoder/results/google_places_search.rb +52 -0
- data/lib/geocoder/results/google_premier.rb +6 -0
- data/lib/geocoder/results/here.rb +79 -0
- data/lib/geocoder/results/ip2location.rb +22 -0
- data/lib/geocoder/results/ipapi_com.rb +45 -0
- data/lib/geocoder/results/ipdata_co.rb +40 -0
- data/lib/geocoder/results/ipinfo_io.rb +48 -0
- data/lib/geocoder/results/ipstack.rb +60 -0
- data/lib/geocoder/results/latlon.rb +71 -0
- data/lib/geocoder/results/location_iq.rb +6 -0
- data/lib/geocoder/results/mapbox.rb +57 -0
- data/lib/geocoder/results/mapquest.rb +48 -0
- data/lib/geocoder/results/maxmind.rb +130 -0
- data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
- data/lib/geocoder/results/maxmind_local.rb +44 -0
- data/lib/geocoder/results/nominatim.rb +109 -0
- data/lib/geocoder/results/opencagedata.rb +100 -0
- data/lib/geocoder/results/pelias.rb +58 -0
- data/lib/geocoder/results/pickpoint.rb +6 -0
- data/lib/geocoder/results/pointpin.rb +40 -0
- data/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
- data/lib/geocoder/results/postcodes_io.rb +40 -0
- data/lib/geocoder/results/smarty_streets.rb +142 -0
- data/lib/geocoder/results/telize.rb +40 -0
- data/lib/geocoder/results/tencent.rb +72 -0
- data/lib/geocoder/results/test.rb +33 -0
- data/lib/geocoder/results/yandex.rb +134 -0
- data/lib/geocoder/sql.rb +110 -0
- data/lib/geocoder/stores/active_record.rb +328 -0
- data/lib/geocoder/stores/base.rb +115 -0
- data/lib/geocoder/stores/mongo_base.rb +58 -0
- data/lib/geocoder/stores/mongo_mapper.rb +13 -0
- data/lib/geocoder/stores/mongoid.rb +13 -0
- data/lib/geocoder/version.rb +3 -0
- data/lib/hash_recursive_merge.rb +74 -0
- data/lib/maxmind_database.rb +109 -0
- data/lib/tasks/geocoder.rake +54 -0
- data/lib/tasks/maxmind.rake +73 -0
- metadata +186 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/maxmind'
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
module Geocoder::Lookup
|
6
|
+
class Maxmind < Base
|
7
|
+
|
8
|
+
def name
|
9
|
+
"MaxMind"
|
10
|
+
end
|
11
|
+
|
12
|
+
private # ---------------------------------------------------------------
|
13
|
+
|
14
|
+
def base_query_url(query)
|
15
|
+
"#{protocol}://geoip.maxmind.com/#{service_code}?"
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Return the name of the configured service, or raise an exception.
|
20
|
+
#
|
21
|
+
def configured_service!
|
22
|
+
if s = configuration[:service] and services.keys.include?(s)
|
23
|
+
return s
|
24
|
+
else
|
25
|
+
raise(
|
26
|
+
Geocoder::ConfigurationError,
|
27
|
+
"When using MaxMind you MUST specify a service name: " +
|
28
|
+
"Geocoder.configure(:maxmind => {:service => ...}), " +
|
29
|
+
"where '...' is one of: #{services.keys.inspect}"
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def service_code
|
35
|
+
services[configured_service!]
|
36
|
+
end
|
37
|
+
|
38
|
+
def service_response_fields_count
|
39
|
+
Geocoder::Result::Maxmind.field_names[configured_service!].size
|
40
|
+
end
|
41
|
+
|
42
|
+
def data_contains_error?(parsed_data)
|
43
|
+
# if all fields given then there is an error
|
44
|
+
parsed_data.size == service_response_fields_count and !parsed_data.last.nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Service names mapped to code used in URL.
|
49
|
+
#
|
50
|
+
def services
|
51
|
+
{
|
52
|
+
:country => "a",
|
53
|
+
:city => "b",
|
54
|
+
:city_isp_org => "f",
|
55
|
+
:omni => "e"
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def results(query)
|
60
|
+
# don't look up a loopback or private address, just return the stored result
|
61
|
+
return [reserved_result] if query.internal_ip_address?
|
62
|
+
doc = fetch_data(query)
|
63
|
+
if doc and doc.is_a?(Array)
|
64
|
+
if !data_contains_error?(doc)
|
65
|
+
return [doc]
|
66
|
+
elsif doc.last == "INVALID_LICENSE_KEY"
|
67
|
+
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid MaxMind API key.")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
return []
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_raw_data(raw_data)
|
74
|
+
# Maxmind just returns text/plain as csv format but according to documentation,
|
75
|
+
# we get ISO-8859-1 encoded string. We need to convert it.
|
76
|
+
CSV.parse_line raw_data.force_encoding("ISO-8859-1").encode("UTF-8")
|
77
|
+
end
|
78
|
+
|
79
|
+
def reserved_result
|
80
|
+
",,,,0,0,0,0,,,".split(",")
|
81
|
+
end
|
82
|
+
|
83
|
+
def query_url_params(query)
|
84
|
+
{
|
85
|
+
:l => configuration.api_key,
|
86
|
+
:i => query.sanitized_text
|
87
|
+
}.merge(super)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/maxmind_geoip2'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class MaxmindGeoip2 < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"MaxMind GeoIP2"
|
9
|
+
end
|
10
|
+
|
11
|
+
# Maxmind's GeoIP2 Precision Services only supports HTTPS,
|
12
|
+
# otherwise a `404 Not Found` HTTP response will be returned
|
13
|
+
def supported_protocols
|
14
|
+
[:https]
|
15
|
+
end
|
16
|
+
|
17
|
+
def query_url(query)
|
18
|
+
"#{protocol}://geoip.maxmind.com/geoip/v2.1/#{configured_service!}/#{query.sanitized_text.strip}"
|
19
|
+
end
|
20
|
+
|
21
|
+
private # ---------------------------------------------------------------
|
22
|
+
|
23
|
+
def cache_key(query)
|
24
|
+
query_url(query)
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Return the name of the configured service, or raise an exception.
|
29
|
+
#
|
30
|
+
def configured_service!
|
31
|
+
if s = configuration[:service] and services.include?(s) and configuration[:basic_auth][:user] and configuration[:basic_auth][:password]
|
32
|
+
return s
|
33
|
+
else
|
34
|
+
raise(
|
35
|
+
Geocoder::ConfigurationError, "When using MaxMind GeoIP2 you must specify a service and credentials: Geocoder.configure(maxmind_geoip2: {service: ..., basic_auth: {user: ..., password: ...}}), where service is one of: #{services.inspect}"
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def data_contains_error?(doc)
|
41
|
+
(["code", "error"] - doc.keys).empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Service names used in URL.
|
46
|
+
#
|
47
|
+
def services
|
48
|
+
[
|
49
|
+
:country,
|
50
|
+
:city,
|
51
|
+
:insights,
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
def results(query)
|
56
|
+
# don't look up a loopback or private address, just return the stored result
|
57
|
+
return [] if query.internal_ip_address?
|
58
|
+
|
59
|
+
doc = fetch_data(query)
|
60
|
+
if doc
|
61
|
+
if !data_contains_error?(doc)
|
62
|
+
return [doc]
|
63
|
+
else
|
64
|
+
Geocoder.log(:warn, "MaxMind GeoIP2 Geocoding API error: #{doc['code']} (#{doc['error']}).")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
return []
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
require 'geocoder/lookups/base'
|
3
|
+
require 'geocoder/results/maxmind_local'
|
4
|
+
|
5
|
+
module Geocoder::Lookup
|
6
|
+
class MaxmindLocal < Base
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
if !configuration[:file].nil?
|
10
|
+
begin
|
11
|
+
gem = RUBY_PLATFORM == 'java' ? 'jgeoip' : 'geoip'
|
12
|
+
require gem
|
13
|
+
rescue LoadError
|
14
|
+
raise "Could not load geoip dependency. To use MaxMind Local lookup you must add the #{gem} gem to your Gemfile or have it installed in your system."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
"MaxMind Local"
|
22
|
+
end
|
23
|
+
|
24
|
+
def required_api_key_parts
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def results(query)
|
31
|
+
if configuration[:file]
|
32
|
+
geoip_class = RUBY_PLATFORM == "java" ? JGeoIP : GeoIP
|
33
|
+
result = geoip_class.new(configuration[:file]).city(query.to_s)
|
34
|
+
result.nil? ? [] : [encode_hash(result.to_hash)]
|
35
|
+
elsif configuration[:package] == :city
|
36
|
+
addr = IPAddr.new(query.text).to_i
|
37
|
+
q = "SELECT l.country, l.region, l.city, l.latitude, l.longitude
|
38
|
+
FROM maxmind_geolite_city_location l WHERE l.loc_id = (SELECT b.loc_id FROM maxmind_geolite_city_blocks b
|
39
|
+
WHERE b.start_ip_num <= #{addr} AND #{addr} <= b.end_ip_num)"
|
40
|
+
format_result(q, [:country_name, :region_name, :city_name, :latitude, :longitude])
|
41
|
+
elsif configuration[:package] == :country
|
42
|
+
addr = IPAddr.new(query.text).to_i
|
43
|
+
q = "SELECT country, country_code FROM maxmind_geolite_country
|
44
|
+
WHERE start_ip_num <= #{addr} AND #{addr} <= end_ip_num"
|
45
|
+
format_result(q, [:country_name, :country_code2])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def encode_hash(hash, encoding = "UTF-8")
|
50
|
+
hash.inject({}) do |h,i|
|
51
|
+
h[i[0]] = i[1].is_a?(String) ? i[1].encode(encoding) : i[1]
|
52
|
+
h
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def format_result(query, attr_names)
|
57
|
+
if r = ActiveRecord::Base.connection.execute(query).first
|
58
|
+
r = r.values if r.is_a?(Hash) # some db adapters return Hash, some Array
|
59
|
+
[Hash[*attr_names.zip(r).flatten]]
|
60
|
+
else
|
61
|
+
[]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/nominatim"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Nominatim < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Nominatim"
|
9
|
+
end
|
10
|
+
|
11
|
+
def map_link_url(coordinates)
|
12
|
+
"https://www.openstreetmap.org/?lat=#{coordinates[0]}&lon=#{coordinates[1]}&zoom=15&layers=M"
|
13
|
+
end
|
14
|
+
|
15
|
+
private # ---------------------------------------------------------------
|
16
|
+
|
17
|
+
def base_query_url(query)
|
18
|
+
method = query.reverse_geocode? ? "reverse" : "search"
|
19
|
+
"#{protocol}://#{configured_host}/#{method}?"
|
20
|
+
end
|
21
|
+
|
22
|
+
def configured_host
|
23
|
+
configuration[:host] || "nominatim.openstreetmap.org"
|
24
|
+
end
|
25
|
+
|
26
|
+
def use_ssl?
|
27
|
+
# nominatim.openstreetmap.org redirects HTTP requests to HTTPS
|
28
|
+
if configured_host == "nominatim.openstreetmap.org"
|
29
|
+
true
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def results(query)
|
36
|
+
return [] unless doc = fetch_data(query)
|
37
|
+
doc.is_a?(Array) ? doc : [doc]
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_raw_data(raw_data)
|
41
|
+
if raw_data.include?("Bandwidth limit exceeded")
|
42
|
+
raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Over API query limit.")
|
43
|
+
else
|
44
|
+
super(raw_data)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def query_url_params(query)
|
49
|
+
params = {
|
50
|
+
:format => "json",
|
51
|
+
:addressdetails => "1",
|
52
|
+
:"accept-language" => (query.language || configuration.language)
|
53
|
+
}.merge(super)
|
54
|
+
if query.reverse_geocode?
|
55
|
+
lat,lon = query.coordinates
|
56
|
+
params[:lat] = lat
|
57
|
+
params[:lon] = lon
|
58
|
+
else
|
59
|
+
params[:q] = query.sanitized_text
|
60
|
+
end
|
61
|
+
params
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/opencagedata'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Opencagedata < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"OpenCageData"
|
9
|
+
end
|
10
|
+
|
11
|
+
def required_api_key_parts
|
12
|
+
["key"]
|
13
|
+
end
|
14
|
+
|
15
|
+
private # ----------------------------------------------------------------
|
16
|
+
|
17
|
+
def base_query_url(query)
|
18
|
+
"#{protocol}://api.opencagedata.com/geocode/v1/json?"
|
19
|
+
end
|
20
|
+
|
21
|
+
def results(query)
|
22
|
+
return [] unless doc = fetch_data(query)
|
23
|
+
# return doc["results"]
|
24
|
+
|
25
|
+
messages = doc['status']['message']
|
26
|
+
case doc['status']['code']
|
27
|
+
when 400 # Error with input
|
28
|
+
raise_error(Geocoder::InvalidRequest, messages) ||
|
29
|
+
Geocoder.log(:warn, "Opencagedata Geocoding API error: #{messages}")
|
30
|
+
when 403 # Key related error
|
31
|
+
raise_error(Geocoder::InvalidApiKey, messages) ||
|
32
|
+
Geocoder.log(:warn, "Opencagedata Geocoding API error: #{messages}")
|
33
|
+
when 402 # Quata Exceeded
|
34
|
+
raise_error(Geocoder::OverQueryLimitError, messages) ||
|
35
|
+
Geocoder.log(:warn, "Opencagedata Geocoding API error: #{messages}")
|
36
|
+
when 500 # Unknown error
|
37
|
+
raise_error(Geocoder::Error, messages) ||
|
38
|
+
Geocoder.log(:warn, "Opencagedata Geocoding API error: #{messages}")
|
39
|
+
end
|
40
|
+
|
41
|
+
return doc["results"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def query_url_params(query)
|
45
|
+
params = {
|
46
|
+
:q => query.sanitized_text,
|
47
|
+
:key => configuration.api_key,
|
48
|
+
:language => (query.language || configuration.language)
|
49
|
+
}.merge(super)
|
50
|
+
|
51
|
+
[:abbrv, :countrycode, :min_confidence, :no_dedupe, :no_annotations, :no_record, :limit].each do |option|
|
52
|
+
unless (option_value = query.options[option]).nil?
|
53
|
+
params[option] = option_value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
unless (bounds = query.options[:bounds]).nil?
|
58
|
+
params[:bounds] = bounds.map{ |point| "%f,%f" % point }.join(',')
|
59
|
+
end
|
60
|
+
|
61
|
+
params
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/pelias'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Pelias < Base
|
6
|
+
def name
|
7
|
+
'Pelias'
|
8
|
+
end
|
9
|
+
|
10
|
+
def endpoint
|
11
|
+
configuration[:endpoint] || 'localhost'
|
12
|
+
end
|
13
|
+
|
14
|
+
def required_api_key_parts
|
15
|
+
['search-XXXX']
|
16
|
+
end
|
17
|
+
|
18
|
+
private # ----------------------------------------------------------------
|
19
|
+
|
20
|
+
def base_query_url(query)
|
21
|
+
query_type = query.reverse_geocode? ? 'reverse' : 'search'
|
22
|
+
"#{protocol}://#{endpoint}/v1/#{query_type}?"
|
23
|
+
end
|
24
|
+
|
25
|
+
def query_url_params(query)
|
26
|
+
params = {
|
27
|
+
api_key: configuration.api_key
|
28
|
+
}.merge(super)
|
29
|
+
|
30
|
+
if query.reverse_geocode?
|
31
|
+
lat, lon = query.coordinates
|
32
|
+
params[:'point.lat'] = lat
|
33
|
+
params[:'point.lon'] = lon
|
34
|
+
else
|
35
|
+
params[:text] = query.text
|
36
|
+
end
|
37
|
+
params
|
38
|
+
end
|
39
|
+
|
40
|
+
def results(query)
|
41
|
+
return [] unless doc = fetch_data(query)
|
42
|
+
|
43
|
+
# not all responses include a meta
|
44
|
+
if doc['meta']
|
45
|
+
error = doc.fetch('results', {}).fetch('error', {})
|
46
|
+
message = error.fetch('type', 'Unknown Error') + ': ' + error.fetch('message', 'No message')
|
47
|
+
log_message = 'Pelias Geocoding API error - ' + message
|
48
|
+
case doc['meta']['status_code']
|
49
|
+
when '200'
|
50
|
+
# nothing to see here
|
51
|
+
when '403'
|
52
|
+
raise_error(Geocoder::RequestDenied, message) || Geocoder.log(:warn, log_message)
|
53
|
+
when '429'
|
54
|
+
raise_error(Geocoder::OverQueryLimitError, message) || Geocoder.log(:warn, log_message)
|
55
|
+
else
|
56
|
+
raise_error(Geocoder::Error, message) || Geocoder.log(:warn, log_message)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
doc['features'] || []
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "geocoder/lookups/nominatim"
|
2
|
+
require "geocoder/results/pickpoint"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Pickpoint < Nominatim
|
6
|
+
def name
|
7
|
+
"Pickpoint"
|
8
|
+
end
|
9
|
+
|
10
|
+
def supported_protocols
|
11
|
+
[:https]
|
12
|
+
end
|
13
|
+
|
14
|
+
def required_api_key_parts
|
15
|
+
["api_key"]
|
16
|
+
end
|
17
|
+
|
18
|
+
private # ----------------------------------------------------------------
|
19
|
+
|
20
|
+
def base_query_url(query)
|
21
|
+
method = query.reverse_geocode? ? "reverse" : "forward"
|
22
|
+
"#{protocol}://api.pickpoint.io/v1/#{method}?"
|
23
|
+
end
|
24
|
+
|
25
|
+
def query_url_params(query)
|
26
|
+
params = {
|
27
|
+
key: configuration.api_key
|
28
|
+
}.merge(super)
|
29
|
+
end
|
30
|
+
|
31
|
+
def results(query)
|
32
|
+
return [] unless doc = fetch_data(query)
|
33
|
+
|
34
|
+
if !doc.is_a?(Array) && doc['message'] == 'Unauthorized'
|
35
|
+
raise_error(Geocoder::InvalidApiKey, 'Unauthorized')
|
36
|
+
end
|
37
|
+
|
38
|
+
doc.is_a?(Array) ? doc : [doc]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|