geocoder 1.1.9 → 1.8.0
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 +309 -0
- data/LICENSE +1 -1
- data/README.md +544 -540
- data/bin/console +13 -0
- data/examples/app_defined_lookup_services.rb +22 -0
- data/examples/reverse_geocode_job.rb +40 -0
- data/lib/easting_northing.rb +171 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +22 -16
- 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/cache.rb +20 -32
- 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/calculations.rb +67 -36
- data/lib/geocoder/cli.rb +2 -2
- data/lib/geocoder/configuration.rb +33 -16
- data/lib/geocoder/configuration_hash.rb +4 -4
- data/lib/geocoder/esri_token.rb +38 -0
- data/lib/geocoder/exceptions.rb +19 -0
- data/lib/geocoder/ip_address.rb +33 -0
- data/lib/geocoder/kernel_logger.rb +25 -0
- data/lib/geocoder/logger.rb +47 -0
- data/lib/geocoder/lookup.rb +74 -11
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/amap.rb +63 -0
- data/lib/geocoder/lookups/amazon_location_service.rb +54 -0
- data/lib/geocoder/lookups/baidu.rb +24 -15
- data/lib/geocoder/lookups/baidu_ip.rb +30 -0
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +143 -0
- data/lib/geocoder/lookups/base.rb +109 -23
- data/lib/geocoder/lookups/bing.rb +45 -10
- data/lib/geocoder/lookups/db_ip_com.rb +52 -0
- data/lib/geocoder/lookups/dstk.rb +4 -2
- data/lib/geocoder/lookups/esri.rb +61 -8
- data/lib/geocoder/lookups/freegeoip.rb +25 -6
- data/lib/geocoder/lookups/geoapify.rb +72 -0
- data/lib/geocoder/lookups/geocoder_ca.rb +5 -6
- data/lib/geocoder/lookups/geocodio.rb +42 -0
- data/lib/geocoder/lookups/geoip2.rb +49 -0
- data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
- data/lib/geocoder/lookups/google.rb +45 -12
- data/lib/geocoder/lookups/google_places_details.rb +64 -0
- data/lib/geocoder/lookups/google_places_search.rb +76 -0
- data/lib/geocoder/lookups/google_premier.rb +16 -2
- data/lib/geocoder/lookups/here.rb +73 -0
- data/lib/geocoder/lookups/ip2location.rb +71 -0
- data/lib/geocoder/lookups/ipapi_com.rb +82 -0
- data/lib/geocoder/lookups/ipdata_co.rb +62 -0
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +44 -0
- data/lib/geocoder/lookups/ipqualityscore.rb +50 -0
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/ipstack.rb +63 -0
- data/lib/geocoder/lookups/latlon.rb +58 -0
- data/lib/geocoder/lookups/location_iq.rb +54 -0
- data/lib/geocoder/lookups/mapbox.rb +59 -0
- data/lib/geocoder/lookups/mapquest.rb +9 -10
- data/lib/geocoder/lookups/maxmind.rb +10 -8
- data/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
- data/lib/geocoder/lookups/maxmind_local.rb +71 -0
- data/lib/geocoder/lookups/melissa_street.rb +41 -0
- data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/lib/geocoder/lookups/nominatim.rb +26 -6
- data/lib/geocoder/lookups/opencagedata.rb +65 -0
- data/lib/geocoder/lookups/osmnames.rb +57 -0
- data/lib/geocoder/lookups/pelias.rb +63 -0
- data/lib/geocoder/lookups/photon.rb +89 -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 +68 -0
- data/lib/geocoder/lookups/telize.rb +75 -0
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/lookups/test.rb +4 -0
- data/lib/geocoder/lookups/twogis.rb +58 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +18 -11
- data/lib/geocoder/models/active_record.rb +9 -4
- data/lib/geocoder/models/base.rb +1 -4
- data/lib/geocoder/models/mongo_base.rb +6 -4
- data/lib/geocoder/query.rb +23 -5
- data/lib/geocoder/railtie.rb +2 -2
- data/lib/geocoder/request.rb +102 -11
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/amap.rb +87 -0
- data/lib/geocoder/results/amazon_location_service.rb +57 -0
- data/lib/geocoder/results/baidu.rb +10 -14
- data/lib/geocoder/results/baidu_ip.rb +62 -0
- data/lib/geocoder/results/ban_data_gouv_fr.rb +282 -0
- data/lib/geocoder/results/base.rb +13 -1
- data/lib/geocoder/results/bing.rb +5 -1
- data/lib/geocoder/results/db_ip_com.rb +58 -0
- data/lib/geocoder/results/esri.rb +35 -8
- data/lib/geocoder/results/freegeoip.rb +2 -7
- data/lib/geocoder/results/geoapify.rb +179 -0
- data/lib/geocoder/results/geocoder_ca.rb +3 -3
- 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 +26 -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/here.rb +77 -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/ipgeolocation.rb +59 -0
- data/lib/geocoder/results/ipinfo_io.rb +48 -0
- data/lib/geocoder/results/ipqualityscore.rb +54 -0
- data/lib/geocoder/results/ipregistry.rb +304 -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 +63 -0
- data/lib/geocoder/results/mapquest.rb +5 -8
- data/lib/geocoder/results/maxmind.rb +0 -5
- data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
- data/lib/geocoder/results/maxmind_local.rb +44 -0
- 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 +41 -14
- data/lib/geocoder/results/opencagedata.rb +100 -0
- data/lib/geocoder/results/osmnames.rb +56 -0
- data/lib/geocoder/results/pelias.rb +58 -0
- data/lib/geocoder/results/photon.rb +119 -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 +20 -3
- data/lib/geocoder/results/twogis.rb +76 -0
- data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/results/yandex.rb +244 -32
- data/lib/geocoder/sql.rb +25 -21
- data/lib/geocoder/stores/active_record.rb +82 -26
- data/lib/geocoder/stores/base.rb +9 -14
- data/lib/geocoder/stores/mongo_base.rb +0 -31
- data/lib/geocoder/util.rb +29 -0
- data/lib/geocoder/version.rb +1 -1
- data/lib/geocoder.rb +6 -13
- data/lib/maxmind_database.rb +109 -0
- data/lib/tasks/geocoder.rake +30 -3
- data/lib/tasks/maxmind.rake +73 -0
- metadata +115 -98
- data/.gitignore +0 -5
- data/.travis.yml +0 -27
- data/Rakefile +0 -25
- data/examples/autoexpire_cache_dalli.rb +0 -62
- data/examples/autoexpire_cache_redis.rb +0 -28
- data/gemfiles/Gemfile.mongoid-2.4.x +0 -15
- data/lib/geocoder/lookups/geocoder_us.rb +0 -39
- data/lib/geocoder/lookups/ovi.rb +0 -62
- data/lib/geocoder/lookups/yahoo.rb +0 -86
- data/lib/geocoder/results/geocoder_us.rb +0 -39
- data/lib/geocoder/results/ovi.rb +0 -62
- data/lib/geocoder/results/yahoo.rb +0 -55
- data/lib/hash_recursive_merge.rb +0 -74
- data/lib/oauth_util.rb +0 -112
- data/test/active_record_test.rb +0 -15
- data/test/cache_test.rb +0 -35
- data/test/calculations_test.rb +0 -211
- data/test/configuration_test.rb +0 -78
- data/test/custom_block_test.rb +0 -32
- data/test/error_handling_test.rb +0 -43
- data/test/fixtures/baidu_invalid_key +0 -1
- data/test/fixtures/baidu_no_results +0 -1
- data/test/fixtures/baidu_reverse +0 -1
- data/test/fixtures/baidu_shanghai_pearl_tower +0 -12
- data/test/fixtures/bing_invalid_key +0 -1
- data/test/fixtures/bing_madison_square_garden +0 -40
- data/test/fixtures/bing_no_results +0 -16
- data/test/fixtures/bing_reverse +0 -42
- data/test/fixtures/esri_madison_square_garden +0 -59
- data/test/fixtures/esri_no_results +0 -8
- data/test/fixtures/esri_reverse +0 -21
- data/test/fixtures/freegeoip_74_200_247_59 +0 -12
- data/test/fixtures/freegeoip_no_results +0 -1
- data/test/fixtures/geocoder_ca_madison_square_garden +0 -1
- data/test/fixtures/geocoder_ca_no_results +0 -1
- data/test/fixtures/geocoder_ca_reverse +0 -34
- data/test/fixtures/geocoder_us_madison_square_garden +0 -1
- data/test/fixtures/geocoder_us_no_results +0 -1
- data/test/fixtures/google_garbage +0 -456
- data/test/fixtures/google_madison_square_garden +0 -57
- data/test/fixtures/google_no_city_data +0 -44
- data/test/fixtures/google_no_locality +0 -51
- data/test/fixtures/google_no_results +0 -4
- data/test/fixtures/google_over_limit +0 -4
- data/test/fixtures/mapquest_error +0 -16
- data/test/fixtures/mapquest_invalid_api_key +0 -16
- data/test/fixtures/mapquest_invalid_request +0 -16
- data/test/fixtures/mapquest_madison_square_garden +0 -52
- data/test/fixtures/mapquest_no_results +0 -16
- data/test/fixtures/maxmind_24_24_24_21 +0 -1
- data/test/fixtures/maxmind_24_24_24_22 +0 -1
- data/test/fixtures/maxmind_24_24_24_23 +0 -1
- data/test/fixtures/maxmind_24_24_24_24 +0 -1
- data/test/fixtures/maxmind_74_200_247_59 +0 -1
- data/test/fixtures/maxmind_invalid_key +0 -1
- data/test/fixtures/maxmind_no_results +0 -1
- data/test/fixtures/nominatim_madison_square_garden +0 -150
- data/test/fixtures/nominatim_no_results +0 -1
- data/test/fixtures/ovi_madison_square_garden +0 -72
- data/test/fixtures/ovi_no_results +0 -8
- data/test/fixtures/yahoo_error +0 -1
- data/test/fixtures/yahoo_invalid_key +0 -2
- data/test/fixtures/yahoo_madison_square_garden +0 -52
- data/test/fixtures/yahoo_no_results +0 -10
- data/test/fixtures/yahoo_over_limit +0 -2
- data/test/fixtures/yandex_invalid_key +0 -1
- data/test/fixtures/yandex_kremlin +0 -48
- data/test/fixtures/yandex_no_city_and_town +0 -112
- data/test/fixtures/yandex_no_results +0 -16
- data/test/geocoder_test.rb +0 -59
- data/test/https_test.rb +0 -16
- data/test/integration/smoke_test.rb +0 -26
- data/test/lookup_test.rb +0 -117
- data/test/method_aliases_test.rb +0 -25
- data/test/mongoid_test.rb +0 -46
- data/test/mongoid_test_helper.rb +0 -43
- data/test/near_test.rb +0 -61
- data/test/oauth_util_test.rb +0 -30
- data/test/proxy_test.rb +0 -36
- data/test/query_test.rb +0 -52
- data/test/request_test.rb +0 -29
- data/test/result_test.rb +0 -42
- data/test/services_test.rb +0 -393
- data/test/test_helper.rb +0 -289
- data/test/test_mode_test.rb +0 -59
|
@@ -16,32 +16,67 @@ module Geocoder::Lookup
|
|
|
16
16
|
["key"]
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def query_url(query)
|
|
20
|
-
"#{protocol}://dev.virtualearth.net/REST/v1/Locations" +
|
|
21
|
-
(query.reverse_geocode? ? "/#{query.sanitized_text}?" : "?") +
|
|
22
|
-
url_query_string(query)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
19
|
private # ---------------------------------------------------------------
|
|
26
20
|
|
|
21
|
+
def base_query_url(query)
|
|
22
|
+
text = CGI.escape(query.sanitized_text.strip)
|
|
23
|
+
url = "#{protocol}://dev.virtualearth.net/REST/v1/Locations/"
|
|
24
|
+
if query.reverse_geocode?
|
|
25
|
+
url + "#{text}?"
|
|
26
|
+
else
|
|
27
|
+
if r = query.options[:region]
|
|
28
|
+
url << "#{r}/"
|
|
29
|
+
end
|
|
30
|
+
# use the more forgiving 'unstructured' query format to allow special
|
|
31
|
+
# chars, newlines, brackets, typos.
|
|
32
|
+
url + "?q=#{text}&"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
27
36
|
def results(query)
|
|
28
37
|
return [] unless doc = fetch_data(query)
|
|
29
38
|
|
|
30
39
|
if doc['statusCode'] == 200
|
|
31
40
|
return doc['resourceSets'].first['estimatedTotal'] > 0 ? doc['resourceSets'].first['resources'] : []
|
|
32
41
|
elsif doc['statusCode'] == 401 and doc["authenticationResultCode"] == "InvalidCredentials"
|
|
33
|
-
raise_error(Geocoder::InvalidApiKey) || warn
|
|
42
|
+
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid Bing API key.")
|
|
43
|
+
elsif doc['statusCode'] == 403
|
|
44
|
+
raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Bing Geocoding API error: Forbidden Request")
|
|
45
|
+
elsif [500, 503].include?(doc['statusCode'])
|
|
46
|
+
raise_error(Geocoder::ServiceUnavailable) ||
|
|
47
|
+
Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
|
|
34
48
|
else
|
|
35
|
-
warn "Bing Geocoding API error: #{doc['statusCode']} (#{doc['statusDescription']})."
|
|
49
|
+
Geocoder.log(:warn, "Bing Geocoding API error: #{doc['statusCode']} (#{doc['statusDescription']}).")
|
|
36
50
|
end
|
|
37
51
|
return []
|
|
38
52
|
end
|
|
39
53
|
|
|
40
54
|
def query_url_params(query)
|
|
41
55
|
{
|
|
42
|
-
:
|
|
43
|
-
:
|
|
56
|
+
key: configuration.api_key,
|
|
57
|
+
culture: (query.language || configuration.language)
|
|
44
58
|
}.merge(super)
|
|
45
59
|
end
|
|
60
|
+
|
|
61
|
+
def check_response_for_errors!(response)
|
|
62
|
+
super
|
|
63
|
+
if server_overloaded?(response)
|
|
64
|
+
raise_error(Geocoder::ServiceUnavailable) ||
|
|
65
|
+
Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def valid_response?(response)
|
|
70
|
+
super(response) and not server_overloaded?(response)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def server_overloaded?(response)
|
|
74
|
+
# Occasionally, the servers processing service requests can be overloaded,
|
|
75
|
+
# and you may receive some responses that contain no results for queries that
|
|
76
|
+
# you would normally receive a result. To identify this situation,
|
|
77
|
+
# check the HTTP headers of the response. If the HTTP header X-MS-BM-WS-INFO is set to 1,
|
|
78
|
+
# it is best to wait a few seconds and try again.
|
|
79
|
+
response['x-ms-bm-ws-info'].to_i == 1
|
|
80
|
+
end
|
|
46
81
|
end
|
|
47
82
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/db_ip_com'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class DbIpCom < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
'DB-IP.com'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def supported_protocols
|
|
12
|
+
[:https, :http]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def required_api_key_parts
|
|
16
|
+
['api_key']
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private # ----------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
def base_query_url(query)
|
|
22
|
+
"#{protocol}://api.db-ip.com/v2/#{configuration.api_key}/#{query.sanitized_text}?"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# Same as query_url but without the api key.
|
|
27
|
+
#
|
|
28
|
+
def cache_key(query)
|
|
29
|
+
"#{protocol}://api.db-ip.com/v2/#{query.sanitized_text}?" + hash_to_query(cache_key_params(query))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def results(query)
|
|
33
|
+
return [] unless (doc = fetch_data(query))
|
|
34
|
+
|
|
35
|
+
case doc['error']
|
|
36
|
+
when 'maximum number of queries per day exceeded'
|
|
37
|
+
raise_error Geocoder::OverQueryLimitError ||
|
|
38
|
+
Geocoder.log(:warn, 'DB-API query limit exceeded.')
|
|
39
|
+
|
|
40
|
+
when 'invalid API key'
|
|
41
|
+
raise_error Geocoder::InvalidApiKey ||
|
|
42
|
+
Geocoder.log(:warn, 'Invalid DB-IP API key.')
|
|
43
|
+
when nil
|
|
44
|
+
[doc]
|
|
45
|
+
|
|
46
|
+
else
|
|
47
|
+
raise_error Geocoder::Error ||
|
|
48
|
+
Geocoder.log(:warn, "Request failed: #{doc['error']}")
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -12,9 +12,11 @@ module Geocoder::Lookup
|
|
|
12
12
|
"Data Science Toolkit"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
private # ----------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
def base_query_url(query)
|
|
16
18
|
host = configuration[:host] || "www.datasciencetoolkit.org"
|
|
17
|
-
"#{protocol}://#{host}/maps/api/geocode/json?"
|
|
19
|
+
"#{protocol}://#{host}/maps/api/geocode/json?"
|
|
18
20
|
end
|
|
19
21
|
end
|
|
20
22
|
end
|
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
require 'geocoder/lookups/base'
|
|
2
2
|
require "geocoder/results/esri"
|
|
3
|
+
require 'geocoder/esri_token'
|
|
3
4
|
|
|
4
5
|
module Geocoder::Lookup
|
|
5
6
|
class Esri < Base
|
|
6
|
-
|
|
7
|
+
|
|
7
8
|
def name
|
|
8
9
|
"Esri"
|
|
9
10
|
end
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"#{protocol}://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/#{search_keyword}?" +
|
|
15
|
-
url_query_string(query)
|
|
16
|
-
end
|
|
12
|
+
def supported_protocols
|
|
13
|
+
[:https]
|
|
14
|
+
end
|
|
17
15
|
|
|
18
16
|
private # ---------------------------------------------------------------
|
|
19
17
|
|
|
18
|
+
def base_query_url(query)
|
|
19
|
+
action = query.reverse_geocode? ? "reverseGeocode" : "find"
|
|
20
|
+
"#{protocol}://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/#{action}?"
|
|
21
|
+
end
|
|
22
|
+
|
|
20
23
|
def results(query)
|
|
21
24
|
return [] unless doc = fetch_data(query)
|
|
22
25
|
|
|
23
26
|
if (!query.reverse_geocode?)
|
|
24
|
-
return [] if doc['locations'].empty?
|
|
27
|
+
return [] if !doc['locations'] || doc['locations'].empty?
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
if (doc['error'].nil?)
|
|
@@ -41,8 +44,58 @@ module Geocoder::Lookup
|
|
|
41
44
|
else
|
|
42
45
|
params[:text] = query.sanitized_text
|
|
43
46
|
end
|
|
47
|
+
|
|
48
|
+
params[:token] = token(query)
|
|
49
|
+
|
|
50
|
+
if for_storage_value = for_storage(query)
|
|
51
|
+
params[:forStorage] = for_storage_value
|
|
52
|
+
end
|
|
53
|
+
params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
|
|
54
|
+
params[:preferredLabelValues] = configuration[:preferred_label_values] if configuration[:preferred_label_values]
|
|
55
|
+
|
|
44
56
|
params.merge(super)
|
|
45
57
|
end
|
|
46
58
|
|
|
59
|
+
def for_storage(query)
|
|
60
|
+
if query.options.has_key?(:for_storage)
|
|
61
|
+
query.options[:for_storage]
|
|
62
|
+
else
|
|
63
|
+
configuration[:for_storage]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def token(query)
|
|
68
|
+
token_instance = if query.options[:token]
|
|
69
|
+
query.options[:token]
|
|
70
|
+
else
|
|
71
|
+
configuration[:token]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if !valid_token_configured?(token_instance) && configuration.api_key
|
|
75
|
+
token_instance = create_and_save_token!(query)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
token_instance.to_s unless token_instance.nil?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def valid_token_configured?(token_instance)
|
|
82
|
+
!token_instance.nil? && token_instance.active?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def create_and_save_token!(query)
|
|
86
|
+
token_instance = create_token
|
|
87
|
+
|
|
88
|
+
if query.options[:token]
|
|
89
|
+
query.options[:token] = token_instance
|
|
90
|
+
else
|
|
91
|
+
Geocoder.merge_into_lookup_config(:esri, token: token_instance)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
token_instance
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def create_token
|
|
98
|
+
Geocoder::EsriToken.generate_token(*configuration.api_key)
|
|
99
|
+
end
|
|
47
100
|
end
|
|
48
101
|
end
|
|
@@ -8,19 +8,34 @@ module Geocoder::Lookup
|
|
|
8
8
|
"FreeGeoIP"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def
|
|
12
|
-
|
|
11
|
+
def supported_protocols
|
|
12
|
+
if configuration[:host]
|
|
13
|
+
[:https]
|
|
14
|
+
else
|
|
15
|
+
# use https for default host
|
|
16
|
+
[:https]
|
|
17
|
+
end
|
|
13
18
|
end
|
|
14
19
|
|
|
15
20
|
private # ---------------------------------------------------------------
|
|
16
21
|
|
|
22
|
+
def base_query_url(query)
|
|
23
|
+
"#{protocol}://#{host}/json/#{query.sanitized_text}?"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def query_url_params(query)
|
|
27
|
+
{
|
|
28
|
+
:apikey => configuration.api_key
|
|
29
|
+
}.merge(super)
|
|
30
|
+
end
|
|
31
|
+
|
|
17
32
|
def parse_raw_data(raw_data)
|
|
18
33
|
raw_data.match(/^<html><title>404/) ? nil : super(raw_data)
|
|
19
34
|
end
|
|
20
35
|
|
|
21
36
|
def results(query)
|
|
22
|
-
# don't look up a loopback address, just return the stored result
|
|
23
|
-
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?
|
|
24
39
|
# note: Freegeoip.net returns plain text "Not Found" on bad request
|
|
25
40
|
(doc = fetch_data(query)) ? [doc] : []
|
|
26
41
|
end
|
|
@@ -31,13 +46,17 @@ module Geocoder::Lookup
|
|
|
31
46
|
"city" => "",
|
|
32
47
|
"region_code" => "",
|
|
33
48
|
"region_name" => "",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
49
|
+
"metro_code" => "",
|
|
50
|
+
"zip_code" => "",
|
|
36
51
|
"latitude" => "0",
|
|
37
52
|
"longitude" => "0",
|
|
38
53
|
"country_name" => "Reserved",
|
|
39
54
|
"country_code" => "RD"
|
|
40
55
|
}
|
|
41
56
|
end
|
|
57
|
+
|
|
58
|
+
def host
|
|
59
|
+
configuration[:host] || "freegeoip.app"
|
|
60
|
+
end
|
|
42
61
|
end
|
|
43
62
|
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
|
|
@@ -8,12 +8,12 @@ module Geocoder::Lookup
|
|
|
8
8
|
"Geocoder.ca"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def query_url(query)
|
|
12
|
-
"#{protocol}://geocoder.ca/?" + url_query_string(query)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
11
|
private # ---------------------------------------------------------------
|
|
16
12
|
|
|
13
|
+
def base_query_url(query)
|
|
14
|
+
"#{protocol}://geocoder.ca/?"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
17
|
def results(query)
|
|
18
18
|
return [] unless doc = fetch_data(query)
|
|
19
19
|
if doc['error'].nil?
|
|
@@ -21,7 +21,7 @@ module Geocoder::Lookup
|
|
|
21
21
|
elsif doc['error']['code'] == "005"
|
|
22
22
|
# "Postal Code is not in the proper Format" => no results, just shut up
|
|
23
23
|
else
|
|
24
|
-
warn "Geocoder.ca service error: #{doc['error']['code']} (#{doc['error']['description']})."
|
|
24
|
+
Geocoder.log(:warn, "Geocoder.ca service error: #{doc['error']['code']} (#{doc['error']['description']}).")
|
|
25
25
|
end
|
|
26
26
|
return []
|
|
27
27
|
end
|
|
@@ -51,4 +51,3 @@ module Geocoder::Lookup
|
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
|
-
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require "geocoder/results/geocodio"
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class Geocodio < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"Geocodio"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def results(query)
|
|
12
|
+
return [] unless doc = fetch_data(query)
|
|
13
|
+
return doc["results"] if doc['error'].nil?
|
|
14
|
+
|
|
15
|
+
if doc['error'] == 'Invalid API key'
|
|
16
|
+
raise_error(Geocoder::InvalidApiKey) ||
|
|
17
|
+
Geocoder.log(:warn, "Geocodio service error: invalid API key.")
|
|
18
|
+
elsif doc['error'].match(/You have reached your daily maximum/)
|
|
19
|
+
raise_error(Geocoder::OverQueryLimitError, doc['error']) ||
|
|
20
|
+
Geocoder.log(:warn, "Geocodio service error: #{doc['error']}.")
|
|
21
|
+
else
|
|
22
|
+
raise_error(Geocoder::InvalidRequest, doc['error']) ||
|
|
23
|
+
Geocoder.log(:warn, "Geocodio service error: #{doc['error']}.")
|
|
24
|
+
end
|
|
25
|
+
[]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private # ---------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
def base_query_url(query)
|
|
31
|
+
path = query.reverse_geocode? ? "reverse" : "geocode"
|
|
32
|
+
"#{protocol}://api.geocod.io/v1.6/#{path}?"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def query_url_params(query)
|
|
36
|
+
{
|
|
37
|
+
:api_key => configuration.api_key,
|
|
38
|
+
:q => query.sanitized_text
|
|
39
|
+
}.merge(super)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/geoip2'
|
|
3
|
+
|
|
4
|
+
module Geocoder
|
|
5
|
+
module Lookup
|
|
6
|
+
class Geoip2 < Base
|
|
7
|
+
attr_reader :gem_name
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
unless configuration[:file].nil?
|
|
11
|
+
begin
|
|
12
|
+
@gem_name = configuration[:lib] || 'maxminddb'
|
|
13
|
+
require @gem_name
|
|
14
|
+
rescue LoadError
|
|
15
|
+
raise "Could not load Maxmind DB dependency. To use the GeoIP2 lookup you must add the #{@gem_name} gem to your Gemfile or have it installed in your system."
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
@mmdb = db_class.new(configuration[:file].to_s)
|
|
19
|
+
end
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def name
|
|
24
|
+
'GeoIP2'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def required_api_key_parts
|
|
28
|
+
[]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def db_class
|
|
34
|
+
gem_name == 'hive_geoip2' ? Hive::GeoIP2 : MaxMindDB
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def results(query)
|
|
38
|
+
return [] unless configuration[:file]
|
|
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
|
+
|
|
44
|
+
result = @mmdb.lookup(query.to_s)
|
|
45
|
+
result.nil? ? [] : [result]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require "geocoder/results/geoportail_lu"
|
|
3
|
+
|
|
4
|
+
module Geocoder
|
|
5
|
+
module Lookup
|
|
6
|
+
class GeoportailLu < Base
|
|
7
|
+
|
|
8
|
+
def name
|
|
9
|
+
"Geoportail.lu"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private # ---------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
def base_query_url(query)
|
|
15
|
+
if query.reverse_geocode?
|
|
16
|
+
reverse_geocode_url_base_path
|
|
17
|
+
else
|
|
18
|
+
search_url_base_path
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def search_url_base_path
|
|
23
|
+
"#{protocol}://api.geoportail.lu/geocoder/search?"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def reverse_geocode_url_base_path
|
|
27
|
+
"#{protocol}://api.geoportail.lu/geocoder/reverseGeocode?"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def query_url_geoportail_lu_params(query)
|
|
31
|
+
query.reverse_geocode? ? reverse_geocode_params(query) : search_params(query)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def search_params(query)
|
|
35
|
+
{
|
|
36
|
+
queryString: query.sanitized_text
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def reverse_geocode_params(query)
|
|
41
|
+
lat_lon = query.coordinates
|
|
42
|
+
{
|
|
43
|
+
lat: lat_lon.first,
|
|
44
|
+
lon: lat_lon.last
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def query_url_params(query)
|
|
49
|
+
query_url_geoportail_lu_params(query).merge(super)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def results(query)
|
|
53
|
+
return [] unless doc = fetch_data(query)
|
|
54
|
+
if doc['success'] == true
|
|
55
|
+
result = doc['results']
|
|
56
|
+
else
|
|
57
|
+
result = []
|
|
58
|
+
raise_error(Geocoder::Error) ||
|
|
59
|
+
warn("Geportail.lu Geocoding API error")
|
|
60
|
+
end
|
|
61
|
+
result
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -12,40 +12,70 @@ module Geocoder::Lookup
|
|
|
12
12
|
"http://maps.google.com/maps?q=#{coordinates.join(',')}"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def
|
|
16
|
-
|
|
15
|
+
def supported_protocols
|
|
16
|
+
# Google requires HTTPS if an API key is used.
|
|
17
|
+
if configuration.api_key
|
|
18
|
+
[:https]
|
|
19
|
+
else
|
|
20
|
+
[:http, :https]
|
|
21
|
+
end
|
|
17
22
|
end
|
|
18
23
|
|
|
19
24
|
private # ---------------------------------------------------------------
|
|
20
25
|
|
|
26
|
+
def base_query_url(query)
|
|
27
|
+
"#{protocol}://maps.googleapis.com/maps/api/geocode/json?"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def configure_ssl!(client)
|
|
31
|
+
client.instance_eval {
|
|
32
|
+
@ssl_context = OpenSSL::SSL::SSLContext.new
|
|
33
|
+
options = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
|
|
34
|
+
if OpenSSL::SSL.const_defined?('OP_NO_COMPRESSION')
|
|
35
|
+
options |= OpenSSL::SSL::OP_NO_COMPRESSION
|
|
36
|
+
end
|
|
37
|
+
@ssl_context.set_params({options: options})
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
21
41
|
def valid_response?(response)
|
|
22
|
-
|
|
42
|
+
json = parse_json(response.body)
|
|
43
|
+
status = json["status"] if json
|
|
23
44
|
super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
|
|
24
45
|
end
|
|
25
46
|
|
|
47
|
+
def result_root_attr
|
|
48
|
+
'results'
|
|
49
|
+
end
|
|
50
|
+
|
|
26
51
|
def results(query)
|
|
27
52
|
return [] unless doc = fetch_data(query)
|
|
28
|
-
case doc['status']
|
|
29
|
-
|
|
53
|
+
case doc['status']
|
|
54
|
+
when "OK" # OK status implies >0 results
|
|
55
|
+
return doc[result_root_attr]
|
|
30
56
|
when "OVER_QUERY_LIMIT"
|
|
31
57
|
raise_error(Geocoder::OverQueryLimitError) ||
|
|
32
|
-
warn
|
|
58
|
+
Geocoder.log(:warn, "#{name} API error: over query limit.")
|
|
33
59
|
when "REQUEST_DENIED"
|
|
34
|
-
raise_error(Geocoder::RequestDenied) ||
|
|
35
|
-
warn
|
|
60
|
+
raise_error(Geocoder::RequestDenied, doc['error_message']) ||
|
|
61
|
+
Geocoder.log(:warn, "#{name} API error: request denied (#{doc['error_message']}).")
|
|
36
62
|
when "INVALID_REQUEST"
|
|
37
|
-
raise_error(Geocoder::InvalidRequest) ||
|
|
38
|
-
warn
|
|
63
|
+
raise_error(Geocoder::InvalidRequest, doc['error_message']) ||
|
|
64
|
+
Geocoder.log(:warn, "#{name} API error: invalid request (#{doc['error_message']}).")
|
|
39
65
|
end
|
|
40
66
|
return []
|
|
41
67
|
end
|
|
42
68
|
|
|
43
69
|
def query_url_google_params(query)
|
|
44
70
|
params = {
|
|
45
|
-
(query.reverse_geocode? ? :latlng : :address) => query.sanitized_text,
|
|
46
71
|
:sensor => "false",
|
|
47
|
-
:language => configuration.language
|
|
72
|
+
:language => (query.language || configuration.language)
|
|
48
73
|
}
|
|
74
|
+
if query.options[:google_place_id]
|
|
75
|
+
params[:place_id] = query.sanitized_text
|
|
76
|
+
else
|
|
77
|
+
params[(query.reverse_geocode? ? :latlng : :address)] = query.sanitized_text
|
|
78
|
+
end
|
|
49
79
|
unless (bounds = query.options[:bounds]).nil?
|
|
50
80
|
params[:bounds] = bounds.map{ |point| "%f,%f" % point }.join('|')
|
|
51
81
|
end
|
|
@@ -55,6 +85,9 @@ module Geocoder::Lookup
|
|
|
55
85
|
unless (components = query.options[:components]).nil?
|
|
56
86
|
params[:components] = components.is_a?(Array) ? components.join("|") : components
|
|
57
87
|
end
|
|
88
|
+
unless (result_type = query.options[:result_type]).nil?
|
|
89
|
+
params[:result_type] = result_type.is_a?(Array) ? result_type.join("|") : result_type
|
|
90
|
+
end
|
|
58
91
|
params
|
|
59
92
|
end
|
|
60
93
|
|