geocoder-kb 1.2.6
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/.gitignore +6 -0
- data/.travis.yml +31 -0
- data/CHANGELOG.md +384 -0
- data/LICENSE +20 -0
- data/README.md +1085 -0
- data/Rakefile +25 -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/sidekiq_worker.rb +16 -0
- data/gemfiles/Gemfile.mongoid-2.4.x +16 -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 +47 -0
- data/lib/geocoder/cache.rb +90 -0
- data/lib/geocoder/calculations.rb +428 -0
- data/lib/geocoder/cli.rb +121 -0
- data/lib/geocoder/configuration.rb +124 -0
- data/lib/geocoder/configuration_hash.rb +11 -0
- data/lib/geocoder/exceptions.rb +21 -0
- data/lib/geocoder/ip_address.rb +21 -0
- data/lib/geocoder/lookup.rb +102 -0
- data/lib/geocoder/lookups/amap.rb +55 -0
- data/lib/geocoder/lookups/baidu.rb +55 -0
- data/lib/geocoder/lookups/baidu_ip.rb +54 -0
- data/lib/geocoder/lookups/base.rb +302 -0
- data/lib/geocoder/lookups/bing.rb +59 -0
- data/lib/geocoder/lookups/dstk.rb +20 -0
- data/lib/geocoder/lookups/esri.rb +48 -0
- data/lib/geocoder/lookups/freegeoip.rb +47 -0
- data/lib/geocoder/lookups/geocoder_ca.rb +54 -0
- data/lib/geocoder/lookups/geocoder_us.rb +39 -0
- data/lib/geocoder/lookups/geocodio.rb +42 -0
- data/lib/geocoder/lookups/geoip2.rb +40 -0
- data/lib/geocoder/lookups/google.rb +67 -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/mapquest.rb +60 -0
- data/lib/geocoder/lookups/maxmind.rb +90 -0
- data/lib/geocoder/lookups/maxmind_local.rb +58 -0
- data/lib/geocoder/lookups/nominatim.rb +52 -0
- data/lib/geocoder/lookups/okf.rb +43 -0
- data/lib/geocoder/lookups/opencagedata.rb +58 -0
- data/lib/geocoder/lookups/ovi.rb +62 -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 +45 -0
- data/lib/geocoder/lookups/telize.rb +40 -0
- data/lib/geocoder/lookups/test.rb +44 -0
- data/lib/geocoder/lookups/yahoo.rb +88 -0
- data/lib/geocoder/lookups/yandex.rb +54 -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 +64 -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 +25 -0
- data/lib/geocoder/results/amap.rb +85 -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 +48 -0
- data/lib/geocoder/results/dstk.rb +6 -0
- data/lib/geocoder/results/esri.rb +51 -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 +66 -0
- data/lib/geocoder/results/geoip2.rb +64 -0
- data/lib/geocoder/results/google.rb +124 -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 +62 -0
- data/lib/geocoder/results/mapquest.rb +51 -0
- data/lib/geocoder/results/maxmind.rb +135 -0
- data/lib/geocoder/results/maxmind_local.rb +49 -0
- data/lib/geocoder/results/nominatim.rb +94 -0
- data/lib/geocoder/results/okf.rb +106 -0
- data/lib/geocoder/results/opencagedata.rb +82 -0
- data/lib/geocoder/results/ovi.rb +62 -0
- data/lib/geocoder/results/pointpin.rb +44 -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/yahoo.rb +55 -0
- data/lib/geocoder/results/yandex.rb +84 -0
- data/lib/geocoder/sql.rb +107 -0
- data/lib/geocoder/stores/active_record.rb +289 -0
- data/lib/geocoder/stores/base.rb +127 -0
- data/lib/geocoder/stores/mongo_base.rb +89 -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/oauth_util.rb +112 -0
- data/lib/tasks/geocoder.rake +29 -0
- data/lib/tasks/maxmind.rake +73 -0
- data/test/fixtures/baidu_invalid_key +1 -0
- data/test/fixtures/baidu_ip_202_198_16_3 +19 -0
- data/test/fixtures/baidu_ip_invalid_key +1 -0
- data/test/fixtures/baidu_ip_no_results +1 -0
- data/test/fixtures/baidu_no_results +1 -0
- data/test/fixtures/baidu_reverse +1 -0
- data/test/fixtures/baidu_shanghai_pearl_tower +12 -0
- data/test/fixtures/bing_invalid_key +1 -0
- data/test/fixtures/bing_madison_square_garden +40 -0
- data/test/fixtures/bing_no_results +16 -0
- data/test/fixtures/bing_reverse +42 -0
- data/test/fixtures/cloudmade_invalid_key +1 -0
- data/test/fixtures/cloudmade_madison_square_garden +1 -0
- data/test/fixtures/cloudmade_no_results +1 -0
- data/test/fixtures/esri_madison_square_garden +59 -0
- data/test/fixtures/esri_no_results +8 -0
- data/test/fixtures/esri_reverse +21 -0
- data/test/fixtures/freegeoip_74_200_247_59 +12 -0
- data/test/fixtures/freegeoip_no_results +1 -0
- data/test/fixtures/geocoder_ca_madison_square_garden +1 -0
- data/test/fixtures/geocoder_ca_no_results +1 -0
- data/test/fixtures/geocoder_ca_reverse +34 -0
- data/test/fixtures/geocoder_us_madison_square_garden +1 -0
- data/test/fixtures/geocoder_us_no_results +1 -0
- data/test/fixtures/geocodio_1101_pennsylvania_ave +1 -0
- data/test/fixtures/geocodio_bad_api_key +3 -0
- data/test/fixtures/geocodio_invalid +4 -0
- data/test/fixtures/geocodio_no_results +1 -0
- data/test/fixtures/geocodio_over_query_limit +4 -0
- data/test/fixtures/google_garbage +456 -0
- data/test/fixtures/google_madison_square_garden +57 -0
- data/test/fixtures/google_no_city_data +44 -0
- data/test/fixtures/google_no_locality +51 -0
- data/test/fixtures/google_no_results +4 -0
- data/test/fixtures/google_over_limit +4 -0
- data/test/fixtures/google_places_details_invalid_request +4 -0
- data/test/fixtures/google_places_details_madison_square_garden +120 -0
- data/test/fixtures/google_places_details_no_results +4 -0
- data/test/fixtures/google_places_details_no_reviews +60 -0
- data/test/fixtures/google_places_details_no_types +66 -0
- data/test/fixtures/here_madison_square_garden +72 -0
- data/test/fixtures/here_no_results +8 -0
- data/test/fixtures/mapquest_error +16 -0
- data/test/fixtures/mapquest_invalid_api_key +16 -0
- data/test/fixtures/mapquest_invalid_request +16 -0
- data/test/fixtures/mapquest_madison_square_garden +52 -0
- data/test/fixtures/mapquest_no_results +16 -0
- data/test/fixtures/maxmind_24_24_24_21 +1 -0
- data/test/fixtures/maxmind_24_24_24_22 +1 -0
- data/test/fixtures/maxmind_24_24_24_23 +1 -0
- data/test/fixtures/maxmind_24_24_24_24 +1 -0
- data/test/fixtures/maxmind_74_200_247_59 +1 -0
- data/test/fixtures/maxmind_invalid_key +1 -0
- data/test/fixtures/maxmind_no_results +1 -0
- data/test/fixtures/nominatim_madison_square_garden +150 -0
- data/test/fixtures/nominatim_no_results +1 -0
- data/test/fixtures/nominatim_over_limit +1 -0
- data/test/fixtures/okf_kirstinmaki +67 -0
- data/test/fixtures/okf_no_results +4 -0
- data/test/fixtures/opencagedata_invalid_api_key +25 -0
- data/test/fixtures/opencagedata_invalid_request +26 -0
- data/test/fixtures/opencagedata_madison_square_garden +73 -0
- data/test/fixtures/opencagedata_no_results +29 -0
- data/test/fixtures/opencagedata_over_limit +31 -0
- data/test/fixtures/ovi_madison_square_garden +72 -0
- data/test/fixtures/ovi_no_results +8 -0
- data/test/fixtures/pointpin_10_10_10_10 +1 -0
- data/test/fixtures/pointpin_555_555_555_555 +1 -0
- data/test/fixtures/pointpin_80_111_555_555 +1 -0
- data/test/fixtures/pointpin_no_results +1 -0
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_WR26NJ +1 -0
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_generic_error +1 -0
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_hampshire +1 -0
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_key_limit_exceeded +1 -0
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_no_results +1 -0
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_romsey +1 -0
- data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_unknown_key +1 -0
- data/test/fixtures/smarty_streets_11211 +1 -0
- data/test/fixtures/smarty_streets_madison_square_garden +47 -0
- data/test/fixtures/smarty_streets_no_results +1 -0
- data/test/fixtures/telize_10_10_10_10 +1 -0
- data/test/fixtures/telize_555_555_555_555 +4 -0
- data/test/fixtures/telize_74_200_247_59 +1 -0
- data/test/fixtures/telize_no_results +1 -0
- data/test/fixtures/yahoo_error +1 -0
- data/test/fixtures/yahoo_invalid_key +2 -0
- data/test/fixtures/yahoo_madison_square_garden +52 -0
- data/test/fixtures/yahoo_no_results +10 -0
- data/test/fixtures/yahoo_over_limit +2 -0
- data/test/fixtures/yandex_canada_rue_dupuis_14 +446 -0
- data/test/fixtures/yandex_invalid_key +1 -0
- data/test/fixtures/yandex_kremlin +48 -0
- data/test/fixtures/yandex_new_york +1 -0
- data/test/fixtures/yandex_no_city_and_town +112 -0
- data/test/fixtures/yandex_no_results +16 -0
- data/test/integration/http_client_test.rb +31 -0
- data/test/mongoid_test_helper.rb +43 -0
- data/test/test_helper.rb +416 -0
- data/test/unit/active_record_test.rb +16 -0
- data/test/unit/cache_test.rb +37 -0
- data/test/unit/calculations_test.rb +220 -0
- data/test/unit/configuration_test.rb +55 -0
- data/test/unit/error_handling_test.rb +56 -0
- data/test/unit/geocoder_test.rb +78 -0
- data/test/unit/https_test.rb +17 -0
- data/test/unit/ip_address_test.rb +27 -0
- data/test/unit/lookup_test.rb +153 -0
- data/test/unit/lookups/bing_test.rb +68 -0
- data/test/unit/lookups/dstk_test.rb +26 -0
- data/test/unit/lookups/esri_test.rb +48 -0
- data/test/unit/lookups/freegeoip_test.rb +27 -0
- data/test/unit/lookups/geocoder_ca_test.rb +17 -0
- data/test/unit/lookups/geocodio_test.rb +55 -0
- data/test/unit/lookups/geoip2_test.rb +27 -0
- data/test/unit/lookups/google_places_details_test.rb +122 -0
- data/test/unit/lookups/google_premier_test.rb +22 -0
- data/test/unit/lookups/google_test.rb +84 -0
- data/test/unit/lookups/mapquest_test.rb +60 -0
- data/test/unit/lookups/maxmind_local_test.rb +28 -0
- data/test/unit/lookups/maxmind_test.rb +63 -0
- data/test/unit/lookups/nominatim_test.rb +31 -0
- data/test/unit/lookups/okf_test.rb +38 -0
- data/test/unit/lookups/opencagedata_test.rb +64 -0
- data/test/unit/lookups/pointpin_test.rb +30 -0
- data/test/unit/lookups/postcode_anywhere_uk_test.rb +70 -0
- data/test/unit/lookups/smarty_streets_test.rb +71 -0
- data/test/unit/lookups/telize_test.rb +36 -0
- data/test/unit/lookups/yahoo_test.rb +35 -0
- data/test/unit/method_aliases_test.rb +26 -0
- data/test/unit/model_test.rb +38 -0
- data/test/unit/mongoid_test.rb +47 -0
- data/test/unit/near_test.rb +87 -0
- data/test/unit/oauth_util_test.rb +31 -0
- data/test/unit/proxy_test.rb +37 -0
- data/test/unit/query_test.rb +52 -0
- data/test/unit/rake_task_test.rb +21 -0
- data/test/unit/request_test.rb +35 -0
- data/test/unit/result_test.rb +72 -0
- data/test/unit/test_mode_test.rb +70 -0
- metadata +294 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require 'singleton'
|
|
2
|
+
require 'geocoder/configuration_hash'
|
|
3
|
+
|
|
4
|
+
module Geocoder
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Configuration options should be set by passing a hash:
|
|
8
|
+
#
|
|
9
|
+
# Geocoder.configure(
|
|
10
|
+
# :timeout => 5,
|
|
11
|
+
# :lookup => :yandex,
|
|
12
|
+
# :api_key => "2a9fsa983jaslfj982fjasd",
|
|
13
|
+
# :units => :km
|
|
14
|
+
# )
|
|
15
|
+
#
|
|
16
|
+
def self.configure(options = nil, &block)
|
|
17
|
+
if !options.nil?
|
|
18
|
+
Configuration.instance.configure(options)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Read-only access to the singleton's config data.
|
|
24
|
+
#
|
|
25
|
+
def self.config
|
|
26
|
+
Configuration.instance.data
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# Read-only access to lookup-specific config data.
|
|
31
|
+
#
|
|
32
|
+
def self.config_for_lookup(lookup_name)
|
|
33
|
+
data = config.clone
|
|
34
|
+
data.reject!{ |key,value| !Configuration::OPTIONS.include?(key) }
|
|
35
|
+
if config.has_key?(lookup_name)
|
|
36
|
+
data.merge!(config[lookup_name])
|
|
37
|
+
end
|
|
38
|
+
data
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class Configuration
|
|
42
|
+
include Singleton
|
|
43
|
+
|
|
44
|
+
OPTIONS = [
|
|
45
|
+
:timeout,
|
|
46
|
+
:lookup,
|
|
47
|
+
:ip_lookup,
|
|
48
|
+
:language,
|
|
49
|
+
:http_headers,
|
|
50
|
+
:use_https,
|
|
51
|
+
:http_proxy,
|
|
52
|
+
:https_proxy,
|
|
53
|
+
:api_key,
|
|
54
|
+
:cache,
|
|
55
|
+
:cache_prefix,
|
|
56
|
+
:always_raise,
|
|
57
|
+
:units,
|
|
58
|
+
:distances
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
attr_accessor :data
|
|
62
|
+
|
|
63
|
+
def self.set_defaults
|
|
64
|
+
instance.set_defaults
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
OPTIONS.each do |o|
|
|
68
|
+
define_method o do
|
|
69
|
+
@data[o]
|
|
70
|
+
end
|
|
71
|
+
define_method "#{o}=" do |value|
|
|
72
|
+
@data[o] = value
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def configure(options)
|
|
77
|
+
@data.rmerge!(options)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def initialize # :nodoc
|
|
81
|
+
@data = Geocoder::ConfigurationHash.new
|
|
82
|
+
set_defaults
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def set_defaults
|
|
86
|
+
|
|
87
|
+
# geocoding options
|
|
88
|
+
@data[:timeout] = 3 # geocoding service timeout (secs)
|
|
89
|
+
@data[:lookup] = :google # name of street address geocoding service (symbol)
|
|
90
|
+
@data[:ip_lookup] = :freegeoip # name of IP address geocoding service (symbol)
|
|
91
|
+
@data[:language] = :en # ISO-639 language code
|
|
92
|
+
@data[:http_headers] = {} # HTTP headers for lookup
|
|
93
|
+
@data[:use_https] = false # use HTTPS for lookup requests? (if supported)
|
|
94
|
+
@data[:http_proxy] = nil # HTTP proxy server (user:pass@host:port)
|
|
95
|
+
@data[:https_proxy] = nil # HTTPS proxy server (user:pass@host:port)
|
|
96
|
+
@data[:api_key] = nil # API key for geocoding service
|
|
97
|
+
@data[:cache] = nil # cache object (must respond to #[], #[]=, and #keys)
|
|
98
|
+
@data[:cache_prefix] = "geocoder:" # prefix (string) to use for all cache keys
|
|
99
|
+
|
|
100
|
+
# exceptions that should not be rescued by default
|
|
101
|
+
# (if you want to implement custom error handling);
|
|
102
|
+
# supports SocketError and TimeoutError
|
|
103
|
+
@data[:always_raise] = []
|
|
104
|
+
|
|
105
|
+
# calculation options
|
|
106
|
+
@data[:units] = :mi # :mi or :km
|
|
107
|
+
@data[:distances] = :linear # :linear or :spherical
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
instance_eval(OPTIONS.map do |option|
|
|
111
|
+
o = option.to_s
|
|
112
|
+
<<-EOS
|
|
113
|
+
def #{o}
|
|
114
|
+
instance.data[:#{o}]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def #{o}=(value)
|
|
118
|
+
instance.data[:#{o}] = value
|
|
119
|
+
end
|
|
120
|
+
EOS
|
|
121
|
+
end.join("\n\n"))
|
|
122
|
+
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Geocoder
|
|
2
|
+
|
|
3
|
+
class Error < StandardError
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class ConfigurationError < Error
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class OverQueryLimitError < Error
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class RequestDenied < Error
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class InvalidRequest < Error
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class InvalidApiKey < Error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Geocoder
|
|
2
|
+
class IpAddress < String
|
|
3
|
+
|
|
4
|
+
def loopback?
|
|
5
|
+
valid? and (self == "0.0.0.0" or self.match(/\A127\./) or self == "::1")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def valid?
|
|
9
|
+
ipregex = %r{
|
|
10
|
+
\A( # String Starts
|
|
11
|
+
((::ffff:)?((\d{1,3})\.){3}\d{1,3}) # Check for IPv4
|
|
12
|
+
| # .... Or
|
|
13
|
+
(\S+?(:\S+?){6}\S+) # Check for IPv6
|
|
14
|
+
| # .... Or
|
|
15
|
+
(::1) # IPv6 loopback
|
|
16
|
+
)\z
|
|
17
|
+
}x
|
|
18
|
+
!!self.match(ipregex)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module Geocoder
|
|
2
|
+
module Lookup
|
|
3
|
+
extend self
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Array of valid Lookup service names.
|
|
7
|
+
#
|
|
8
|
+
def all_services
|
|
9
|
+
street_services + ip_services
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Array of valid Lookup service names, excluding :test.
|
|
14
|
+
#
|
|
15
|
+
def all_services_except_test
|
|
16
|
+
all_services - [:test]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# All street address lookup services, default first.
|
|
21
|
+
#
|
|
22
|
+
def street_services
|
|
23
|
+
[
|
|
24
|
+
:dstk,
|
|
25
|
+
:esri,
|
|
26
|
+
:google,
|
|
27
|
+
:google_premier,
|
|
28
|
+
:google_places_details,
|
|
29
|
+
:yahoo,
|
|
30
|
+
:bing,
|
|
31
|
+
:geocoder_ca,
|
|
32
|
+
:geocoder_us,
|
|
33
|
+
:yandex,
|
|
34
|
+
:nominatim,
|
|
35
|
+
:mapquest,
|
|
36
|
+
:opencagedata,
|
|
37
|
+
:ovi,
|
|
38
|
+
:here,
|
|
39
|
+
:baidu,
|
|
40
|
+
:geocodio,
|
|
41
|
+
:smarty_streets,
|
|
42
|
+
:okf,
|
|
43
|
+
:postcode_anywhere_uk,
|
|
44
|
+
:test,
|
|
45
|
+
:amap
|
|
46
|
+
]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
# All IP address lookup services, default first.
|
|
51
|
+
#
|
|
52
|
+
def ip_services
|
|
53
|
+
[
|
|
54
|
+
:baidu_ip,
|
|
55
|
+
:freegeoip,
|
|
56
|
+
:geoip2,
|
|
57
|
+
:maxmind,
|
|
58
|
+
:maxmind_local,
|
|
59
|
+
:telize,
|
|
60
|
+
:pointpin
|
|
61
|
+
]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# Retrieve a Lookup object from the store.
|
|
66
|
+
# Use this instead of Geocoder::Lookup::X.new to get an
|
|
67
|
+
# already-configured Lookup object.
|
|
68
|
+
#
|
|
69
|
+
def get(name)
|
|
70
|
+
@services = {} unless defined?(@services)
|
|
71
|
+
@services[name] = spawn(name) unless @services.include?(name)
|
|
72
|
+
@services[name]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
private # -----------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Spawn a Lookup of the given name.
|
|
80
|
+
#
|
|
81
|
+
def spawn(name)
|
|
82
|
+
if all_services.include?(name)
|
|
83
|
+
Geocoder::Lookup.const_get(classify_name(name)).new
|
|
84
|
+
else
|
|
85
|
+
valids = all_services.map(&:inspect).join(", ")
|
|
86
|
+
raise ConfigurationError, "Please specify a valid lookup for Geocoder " +
|
|
87
|
+
"(#{name.inspect} is not one of: #{valids})."
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
##
|
|
92
|
+
# Convert an "underscore" version of a name into a "class" version.
|
|
93
|
+
#
|
|
94
|
+
def classify_name(filename)
|
|
95
|
+
filename.to_s.split("_").map{ |i| i[0...1].upcase + i[1..-1] }.join
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
Geocoder::Lookup.all_services.each do |name|
|
|
101
|
+
require "geocoder/lookups/#{name}"
|
|
102
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require "geocoder/results/amap"
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class Amap < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"AutoNavi"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def required_api_key_parts
|
|
12
|
+
["key"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def query_url(query)
|
|
16
|
+
path = query.reverse_geocode? ? 'regeo' : 'geo'
|
|
17
|
+
"http://restapi.amap.com/v3/geocode/#{path}?" + url_query_string(query)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private # ---------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
def results(query, reverse = false)
|
|
23
|
+
return [] unless doc = fetch_data(query)
|
|
24
|
+
case doc['status']
|
|
25
|
+
when "1"
|
|
26
|
+
return [doc['regeocode']] unless doc['regeocode'].blank?
|
|
27
|
+
else
|
|
28
|
+
raise_error(Geocoder::Error, "server error.") ||
|
|
29
|
+
warn("#{self.name} Geocoding API error: server error.")
|
|
30
|
+
end
|
|
31
|
+
return []
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def query_url_params(query)
|
|
35
|
+
params = {
|
|
36
|
+
:key => configuration.api_key,
|
|
37
|
+
:output => "json"
|
|
38
|
+
}
|
|
39
|
+
if query.reverse_geocode?
|
|
40
|
+
params[:location] = revert_coordinates(query.text)
|
|
41
|
+
params[:extensions] = "all"
|
|
42
|
+
params[:coordsys] = "gps"
|
|
43
|
+
else
|
|
44
|
+
params[:address] = query.sanitized_text
|
|
45
|
+
end
|
|
46
|
+
params.merge(super)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def revert_coordinates(text)
|
|
50
|
+
[text[1],text[0]].join(",")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require "geocoder/results/baidu"
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class Baidu < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"Baidu"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def required_api_key_parts
|
|
12
|
+
["key"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def query_url(query)
|
|
16
|
+
"http://api.map.baidu.com/geocoder/v2/?" + url_query_string(query)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private # ---------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
def results(query, reverse = false)
|
|
22
|
+
return [] unless doc = fetch_data(query)
|
|
23
|
+
case doc['status']
|
|
24
|
+
when 0
|
|
25
|
+
return [doc['result']] unless doc['result'].blank?
|
|
26
|
+
when 1, 3, 4
|
|
27
|
+
raise_error(Geocoder::Error, "server error.") ||
|
|
28
|
+
warn("Baidu Geocoding API error: server error.")
|
|
29
|
+
when 2
|
|
30
|
+
raise_error(Geocoder::InvalidRequest, "invalid request.") ||
|
|
31
|
+
warn("Baidu Geocoding API error: invalid request.")
|
|
32
|
+
when 5
|
|
33
|
+
raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
|
|
34
|
+
warn("Baidu Geocoding API error: invalid api key.")
|
|
35
|
+
when 101, 102, 200..299
|
|
36
|
+
raise_error(Geocoder::RequestDenied, "request denied") ||
|
|
37
|
+
warn("Baidu Geocoding API error: request denied.")
|
|
38
|
+
when 300..399
|
|
39
|
+
raise_error(Geocoder::OverQueryLimitError, "over query limit.") ||
|
|
40
|
+
warn("Baidu Geocoding API error: over query limit.")
|
|
41
|
+
end
|
|
42
|
+
return []
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def query_url_params(query)
|
|
46
|
+
{
|
|
47
|
+
(query.reverse_geocode? ? :location : :address) => query.sanitized_text,
|
|
48
|
+
:ak => configuration.api_key,
|
|
49
|
+
:output => "json"
|
|
50
|
+
}.merge(super)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/baidu_ip'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class BaiduIp < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"Baidu IP"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def required_api_key_parts
|
|
12
|
+
["key"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def query_url(query)
|
|
16
|
+
"http://api.map.baidu.com/location/ip?" + url_query_string(query)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private # ---------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
def results(query, reverse = false)
|
|
22
|
+
return [] unless doc = fetch_data(query)
|
|
23
|
+
case doc['status']
|
|
24
|
+
when 0
|
|
25
|
+
return [doc['content']] unless doc['content'].blank?
|
|
26
|
+
when 1, 3, 4
|
|
27
|
+
raise_error(Geocoder::Error, "server error.") ||
|
|
28
|
+
warn("Baidu IP Geocoding API error: server error.")
|
|
29
|
+
when 2
|
|
30
|
+
raise_error(Geocoder::InvalidRequest, "invalid request.") ||
|
|
31
|
+
warn("Baidu IP Geocoding API error: invalid request.")
|
|
32
|
+
when 5
|
|
33
|
+
raise_error(Geocoder::InvalidApiKey, "invalid api key.") ||
|
|
34
|
+
warn("Baidu IP Geocoding API error: invalid api key.")
|
|
35
|
+
when 101, 102, 200..299
|
|
36
|
+
raise_error(Geocoder::RequestDenied, "request denied.") ||
|
|
37
|
+
warn("Baidu IP Geocoding API error: request denied.")
|
|
38
|
+
when 300..399
|
|
39
|
+
raise_error(Geocoder::OverQueryLimitError, "over query limit") ||
|
|
40
|
+
warn("Baidu IP Geocoding API error: over query limit.")
|
|
41
|
+
end
|
|
42
|
+
return []
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def query_url_params(query)
|
|
46
|
+
{
|
|
47
|
+
:ip => query.sanitized_text,
|
|
48
|
+
:ak => configuration.api_key,
|
|
49
|
+
:coor => "bd09ll"
|
|
50
|
+
}.merge(super)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|