broken-geocoder 1.3.4
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 +467 -0
- data/LICENSE +20 -0
- data/README.md +1193 -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 +21 -0
- data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +28 -0
- data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +28 -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/geocoder.rb +48 -0
- data/lib/geocoder/cache.rb +90 -0
- data/lib/geocoder/calculations.rb +431 -0
- data/lib/geocoder/cli.rb +121 -0
- data/lib/geocoder/configuration.rb +129 -0
- data/lib/geocoder/configuration_hash.rb +11 -0
- data/lib/geocoder/esri_token.rb +38 -0
- data/lib/geocoder/exceptions.rb +37 -0
- data/lib/geocoder/ip_address.rb +13 -0
- data/lib/geocoder/kernel_logger.rb +25 -0
- data/lib/geocoder/logger.rb +47 -0
- data/lib/geocoder/lookup.rb +110 -0
- data/lib/geocoder/lookups/baidu.rb +59 -0
- data/lib/geocoder/lookups/baidu_ip.rb +59 -0
- data/lib/geocoder/lookups/base.rb +325 -0
- data/lib/geocoder/lookups/bing.rb +80 -0
- data/lib/geocoder/lookups/dstk.rb +20 -0
- data/lib/geocoder/lookups/esri.rb +64 -0
- data/lib/geocoder/lookups/freegeoip.rb +51 -0
- data/lib/geocoder/lookups/geocoder_ca.rb +53 -0
- data/lib/geocoder/lookups/geocoder_us.rb +43 -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 +91 -0
- data/lib/geocoder/lookups/google_places_details.rb +50 -0
- data/lib/geocoder/lookups/google_premier.rb +47 -0
- data/lib/geocoder/lookups/here.rb +62 -0
- data/lib/geocoder/lookups/ipapi_com.rb +86 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +55 -0
- data/lib/geocoder/lookups/latlon.rb +59 -0
- data/lib/geocoder/lookups/mapbox.rb +53 -0
- data/lib/geocoder/lookups/mapquest.rb +59 -0
- data/lib/geocoder/lookups/mapzen.rb +15 -0
- data/lib/geocoder/lookups/maxmind.rb +90 -0
- data/lib/geocoder/lookups/maxmind_geoip2.rb +69 -0
- data/lib/geocoder/lookups/maxmind_local.rb +65 -0
- data/lib/geocoder/lookups/nominatim.rb +52 -0
- data/lib/geocoder/lookups/okf.rb +44 -0
- data/lib/geocoder/lookups/opencagedata.rb +58 -0
- data/lib/geocoder/lookups/ovi.rb +62 -0
- data/lib/geocoder/lookups/pelias.rb +64 -0
- data/lib/geocoder/lookups/pointpin.rb +68 -0
- data/lib/geocoder/lookups/postcode_anywhere_uk.rb +51 -0
- data/lib/geocoder/lookups/smarty_streets.rb +50 -0
- data/lib/geocoder/lookups/telize.rb +55 -0
- data/lib/geocoder/lookups/test.rb +44 -0
- data/lib/geocoder/lookups/yandex.rb +58 -0
- data/lib/geocoder/models/active_record.rb +50 -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 +111 -0
- data/lib/geocoder/railtie.rb +26 -0
- data/lib/geocoder/request.rb +83 -0
- data/lib/geocoder/results/baidu.rb +79 -0
- data/lib/geocoder/results/baidu_ip.rb +62 -0
- data/lib/geocoder/results/base.rb +67 -0
- data/lib/geocoder/results/bing.rb +52 -0
- data/lib/geocoder/results/dstk.rb +6 -0
- data/lib/geocoder/results/esri.rb +75 -0
- data/lib/geocoder/results/freegeoip.rb +45 -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 +70 -0
- data/lib/geocoder/results/geoip2.rb +62 -0
- data/lib/geocoder/results/geoportail_lu.rb +69 -0
- data/lib/geocoder/results/google.rb +139 -0
- data/lib/geocoder/results/google_places_details.rb +35 -0
- data/lib/geocoder/results/google_premier.rb +6 -0
- data/lib/geocoder/results/here.rb +71 -0
- data/lib/geocoder/results/ipapi_com.rb +45 -0
- data/lib/geocoder/results/ipinfo_io.rb +48 -0
- data/lib/geocoder/results/latlon.rb +71 -0
- data/lib/geocoder/results/mapbox.rb +47 -0
- data/lib/geocoder/results/mapquest.rb +48 -0
- data/lib/geocoder/results/mapzen.rb +5 -0
- data/lib/geocoder/results/maxmind.rb +135 -0
- data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
- data/lib/geocoder/results/maxmind_local.rb +49 -0
- data/lib/geocoder/results/nominatim.rb +99 -0
- data/lib/geocoder/results/okf.rb +106 -0
- data/lib/geocoder/results/opencagedata.rb +90 -0
- data/lib/geocoder/results/ovi.rb +71 -0
- data/lib/geocoder/results/pelias.rb +58 -0
- data/lib/geocoder/results/pointpin.rb +40 -0
- data/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
- data/lib/geocoder/results/smarty_streets.rb +106 -0
- data/lib/geocoder/results/telize.rb +45 -0
- data/lib/geocoder/results/test.rb +33 -0
- data/lib/geocoder/results/yandex.rb +92 -0
- data/lib/geocoder/sql.rb +107 -0
- data/lib/geocoder/stores/active_record.rb +305 -0
- data/lib/geocoder/stores/base.rb +116 -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 +38 -0
- data/lib/tasks/maxmind.rake +73 -0
- metadata +167 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require "geocoder/lookups/google"
|
|
2
|
+
require "geocoder/results/google_places_details"
|
|
3
|
+
|
|
4
|
+
module Geocoder
|
|
5
|
+
module Lookup
|
|
6
|
+
class GooglePlacesDetails < Google
|
|
7
|
+
def name
|
|
8
|
+
"Google Places Details"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def required_api_key_parts
|
|
12
|
+
["key"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def supported_protocols
|
|
16
|
+
[:https]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def query_url(query)
|
|
20
|
+
"#{protocol}://maps.googleapis.com/maps/api/place/details/json?#{url_query_string(query)}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def results(query)
|
|
26
|
+
return [] unless doc = fetch_data(query)
|
|
27
|
+
|
|
28
|
+
case doc["status"]
|
|
29
|
+
when "OK"
|
|
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
|
+
[]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def query_url_google_params(query)
|
|
43
|
+
{
|
|
44
|
+
placeid: query.text,
|
|
45
|
+
language: query.language || configuration.language
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'openssl'
|
|
2
|
+
require 'base64'
|
|
3
|
+
require 'geocoder/lookups/google'
|
|
4
|
+
require 'geocoder/results/google_premier'
|
|
5
|
+
|
|
6
|
+
module Geocoder::Lookup
|
|
7
|
+
class GooglePremier < Google
|
|
8
|
+
|
|
9
|
+
def name
|
|
10
|
+
"Google Premier"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def required_api_key_parts
|
|
14
|
+
["private key", "client", "channel"]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def query_url(query)
|
|
18
|
+
path = "/maps/api/geocode/json?" + url_query_string(query)
|
|
19
|
+
"#{protocol}://maps.googleapis.com#{path}&signature=#{sign(path)}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private # ---------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
def query_url_params(query)
|
|
25
|
+
query_url_google_params(query).merge(super).merge(
|
|
26
|
+
:key => nil, # don't use param inherited from Google lookup
|
|
27
|
+
:client => configuration.api_key[1],
|
|
28
|
+
:channel => configuration.api_key[2]
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def sign(string)
|
|
33
|
+
raw_private_key = url_safe_base64_decode(configuration.api_key[0])
|
|
34
|
+
digest = OpenSSL::Digest.new('sha1')
|
|
35
|
+
raw_signature = OpenSSL::HMAC.digest(digest, raw_private_key, string)
|
|
36
|
+
url_safe_base64_encode(raw_signature)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def url_safe_base64_decode(base64_string)
|
|
40
|
+
Base64.decode64(base64_string.tr('-_', '+/'))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def url_safe_base64_encode(raw)
|
|
44
|
+
Base64.encode64(raw).tr('+/', '-_').strip
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/here'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class Here < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"Here"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def required_api_key_parts
|
|
12
|
+
["app_id", "app_code"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def query_url(query)
|
|
16
|
+
"#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.api.here.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?" + url_query_string(query)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private # ---------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
def results(query)
|
|
22
|
+
return [] unless doc = fetch_data(query)
|
|
23
|
+
return [] unless doc['Response'] && doc['Response']['View']
|
|
24
|
+
if r=doc['Response']['View']
|
|
25
|
+
return [] if r.nil? || !r.is_a?(Array) || r.empty?
|
|
26
|
+
return r.first['Result']
|
|
27
|
+
end
|
|
28
|
+
[]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def query_url_params(query)
|
|
32
|
+
options = {
|
|
33
|
+
:gen=>4,
|
|
34
|
+
:app_id=>api_key,
|
|
35
|
+
:app_code=>api_code
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if query.reverse_geocode?
|
|
39
|
+
super.merge(options).merge(
|
|
40
|
+
:prox=>query.sanitized_text,
|
|
41
|
+
:mode=>:retrieveAddresses
|
|
42
|
+
)
|
|
43
|
+
else
|
|
44
|
+
super.merge(options).merge(
|
|
45
|
+
:searchtext=>query.sanitized_text
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def api_key
|
|
51
|
+
if a=configuration.api_key
|
|
52
|
+
return a.first if a.is_a?(Array)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def api_code
|
|
57
|
+
if a=configuration.api_key
|
|
58
|
+
return a.last if a.is_a?(Array)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/ipapi_com'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class IpapiCom < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"ip-api.com"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def query_url(query)
|
|
12
|
+
domain = configuration.api_key ? "pro.ip-api.com" : "ip-api.com"
|
|
13
|
+
url_ = "#{protocol}://#{domain}/json/#{query.sanitized_text}"
|
|
14
|
+
|
|
15
|
+
if (params = url_query_string(query)) && !params.empty?
|
|
16
|
+
url_ + "?" + params
|
|
17
|
+
else
|
|
18
|
+
url_
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def supported_protocols
|
|
23
|
+
if configuration.api_key
|
|
24
|
+
[:http, :https]
|
|
25
|
+
else
|
|
26
|
+
[:http]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def parse_raw_data(raw_data)
|
|
34
|
+
if raw_data.chomp == "invalid key"
|
|
35
|
+
invalid_key_result
|
|
36
|
+
else
|
|
37
|
+
super(raw_data)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def results(query)
|
|
42
|
+
return [reserved_result(query.text)] if query.loopback_ip_address?
|
|
43
|
+
|
|
44
|
+
return [] unless doc = fetch_data(query)
|
|
45
|
+
|
|
46
|
+
if doc["message"] == "invalid key"
|
|
47
|
+
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid API key.")
|
|
48
|
+
return []
|
|
49
|
+
else
|
|
50
|
+
return [doc]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def reserved_result(query)
|
|
55
|
+
{
|
|
56
|
+
"message" => "reserved range",
|
|
57
|
+
"query" => query,
|
|
58
|
+
"status" => "fail",
|
|
59
|
+
"ip" => query,
|
|
60
|
+
"city" => "",
|
|
61
|
+
"region_code" => "",
|
|
62
|
+
"region_name" => "",
|
|
63
|
+
"metrocode" => "",
|
|
64
|
+
"zipcode" => "",
|
|
65
|
+
"latitude" => "0",
|
|
66
|
+
"longitude" => "0",
|
|
67
|
+
"country_name" => "Reserved",
|
|
68
|
+
"country_code" => "RD"
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def invalid_key_result
|
|
73
|
+
{
|
|
74
|
+
"message" => "invalid key"
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def query_url_params(query)
|
|
79
|
+
params = {}
|
|
80
|
+
params.merge!(fields: configuration[:fields]) if configuration.has_key?(:fields)
|
|
81
|
+
params.merge!(key: configuration.api_key) if configuration.api_key
|
|
82
|
+
params.merge(super)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/ipinfo_io'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class IpinfoIo < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"Ipinfo.io"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def query_url(query)
|
|
12
|
+
if configuration.api_key
|
|
13
|
+
"#{protocol}://ipinfo.io/#{query.sanitized_text}/geo?" + url_query_string(query)
|
|
14
|
+
else
|
|
15
|
+
"#{protocol}://ipinfo.io/#{query.sanitized_text}/geo"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# HTTPS available only for paid plans
|
|
20
|
+
def supported_protocols
|
|
21
|
+
if configuration.api_key
|
|
22
|
+
[:http, :https]
|
|
23
|
+
else
|
|
24
|
+
[:http]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private # ---------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
def results(query)
|
|
31
|
+
# don't look up a loopback address, just return the stored result
|
|
32
|
+
return [reserved_result(query.text)] if query.loopback_ip_address?
|
|
33
|
+
if (doc = fetch_data(query)).nil? or doc['code'] == 401 or empty_result?(doc)
|
|
34
|
+
[]
|
|
35
|
+
else
|
|
36
|
+
[doc]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def empty_result?(doc)
|
|
41
|
+
!doc.is_a?(Hash) or doc.keys == ["ip"]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def reserved_result(ip)
|
|
45
|
+
{"message" => "Input string is not a valid IP address", "code" => 401}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def query_url_params(query)
|
|
49
|
+
{
|
|
50
|
+
token: configuration.api_key
|
|
51
|
+
}.merge(super)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/latlon'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class Latlon < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"LatLon.io"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def required_api_key_parts
|
|
12
|
+
["api_key"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def query_url(query)
|
|
16
|
+
"#{protocol}://latlon.io/api/v1/#{'reverse_' if query.reverse_geocode?}geocode?#{url_query_string(query)}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private # ---------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
def results(query)
|
|
22
|
+
return [] unless doc = fetch_data(query)
|
|
23
|
+
if doc['error'].nil?
|
|
24
|
+
[doc]
|
|
25
|
+
# The API returned a 404 response, which indicates no results found
|
|
26
|
+
elsif doc['error']['type'] == 'api_error'
|
|
27
|
+
[]
|
|
28
|
+
elsif
|
|
29
|
+
doc['error']['type'] == 'authentication_error'
|
|
30
|
+
raise_error(Geocoder::InvalidApiKey) ||
|
|
31
|
+
Geocoder.log(:warn, "LatLon.io service error: invalid API key.")
|
|
32
|
+
else
|
|
33
|
+
[]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def supported_protocols
|
|
38
|
+
[:https]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private # ---------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
def query_url_params(query)
|
|
44
|
+
if query.reverse_geocode?
|
|
45
|
+
{
|
|
46
|
+
:token => configuration.api_key,
|
|
47
|
+
:lat => query.coordinates[0],
|
|
48
|
+
:lon => query.coordinates[1]
|
|
49
|
+
}.merge(super)
|
|
50
|
+
else
|
|
51
|
+
{
|
|
52
|
+
:token => configuration.api_key,
|
|
53
|
+
:address => query.sanitized_text
|
|
54
|
+
}.merge(super)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require "geocoder/results/mapbox"
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class Mapbox < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"Mapbox"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def query_url(query)
|
|
12
|
+
"#{protocol}://api.mapbox.com/geocoding/v5/#{dataset}/#{url_query_string(query)}.json?access_token=#{configuration.api_key}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private # ---------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
def results(query)
|
|
18
|
+
return [] unless data = fetch_data(query)
|
|
19
|
+
if data['features']
|
|
20
|
+
sort_relevant_feature(data['features'])
|
|
21
|
+
elsif data['message'] =~ /Invalid\sToken/
|
|
22
|
+
raise_error(Geocoder::InvalidApiKey, data['message'])
|
|
23
|
+
else
|
|
24
|
+
[]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def url_query_string(query)
|
|
29
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI.escape)
|
|
30
|
+
if query.reverse_geocode?
|
|
31
|
+
lat,lon = query.coordinates
|
|
32
|
+
"#{CGI.escape lon},#{CGI.escape lat}"
|
|
33
|
+
else
|
|
34
|
+
CGI.escape query.text.to_s
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def dataset
|
|
39
|
+
configuration[:dataset] || "mapbox.places"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def supported_protocols
|
|
43
|
+
[:https]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def sort_relevant_feature(features)
|
|
47
|
+
# Sort by descending relevance; Favor original order for equal relevance (eg occurs for reverse geocoding)
|
|
48
|
+
features.sort_by do |feature|
|
|
49
|
+
[feature["relevance"],-features.index(feature)]
|
|
50
|
+
end.reverse
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'cgi'
|
|
2
|
+
require 'geocoder/lookups/base'
|
|
3
|
+
require "geocoder/results/mapquest"
|
|
4
|
+
|
|
5
|
+
module Geocoder::Lookup
|
|
6
|
+
class Mapquest < Base
|
|
7
|
+
|
|
8
|
+
def name
|
|
9
|
+
"Mapquest"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def required_api_key_parts
|
|
13
|
+
["key"]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def query_url(query)
|
|
17
|
+
domain = configuration[:open] ? "open" : "www"
|
|
18
|
+
url = "#{protocol}://#{domain}.mapquestapi.com/geocoding/v1/#{search_type(query)}?"
|
|
19
|
+
url + url_query_string(query)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private # ---------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
def search_type(query)
|
|
25
|
+
query.reverse_geocode? ? "reverse" : "address"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def query_url_params(query)
|
|
29
|
+
params = { :location => query.sanitized_text }
|
|
30
|
+
if key = configuration.api_key
|
|
31
|
+
params[:key] = CGI.unescape(key)
|
|
32
|
+
end
|
|
33
|
+
params.merge(super)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# http://www.mapquestapi.com/geocoding/status_codes.html
|
|
37
|
+
# http://open.mapquestapi.com/geocoding/status_codes.html
|
|
38
|
+
def results(query)
|
|
39
|
+
return [] unless doc = fetch_data(query)
|
|
40
|
+
return doc["results"][0]['locations'] if doc['info']['statuscode'] == 0 # A successful geocode call
|
|
41
|
+
|
|
42
|
+
messages = doc['info']['messages'].join
|
|
43
|
+
|
|
44
|
+
case doc['info']['statuscode']
|
|
45
|
+
when 400 # Error with input
|
|
46
|
+
raise_error(Geocoder::InvalidRequest, messages) ||
|
|
47
|
+
Geocoder.log(:warn, "Mapquest Geocoding API error: #{messages}")
|
|
48
|
+
when 403 # Key related error
|
|
49
|
+
raise_error(Geocoder::InvalidApiKey, messages) ||
|
|
50
|
+
Geocoder.log(:warn, "Mapquest Geocoding API error: #{messages}")
|
|
51
|
+
when 500 # Unknown error
|
|
52
|
+
raise_error(Geocoder::Error, messages) ||
|
|
53
|
+
Geocoder.log(:warn, "Mapquest Geocoding API error: #{messages}")
|
|
54
|
+
end
|
|
55
|
+
[]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|