geocoder 1.4.9 → 1.6.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +60 -0
- data/LICENSE +1 -1
- data/README.md +350 -979
- data/bin/console +13 -0
- data/examples/autoexpire_cache_redis.rb +2 -0
- data/lib/easting_northing.rb +171 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +1 -1
- data/lib/geocoder/cache.rb +4 -0
- data/lib/geocoder/calculations.rb +1 -1
- data/lib/geocoder/cli.rb +2 -2
- data/lib/geocoder/configuration.rb +3 -2
- data/lib/geocoder/configuration_hash.rb +4 -4
- data/lib/geocoder/exceptions.rb +1 -1
- data/lib/geocoder/ip_address.rb +16 -2
- data/lib/geocoder/lookup.rb +9 -5
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/amap.rb +7 -3
- data/lib/geocoder/lookups/baidu.rb +14 -10
- data/lib/geocoder/lookups/baidu_ip.rb +7 -36
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +18 -5
- data/lib/geocoder/lookups/base.rb +27 -4
- data/lib/geocoder/lookups/bing.rb +10 -13
- data/lib/geocoder/lookups/db_ip_com.rb +9 -6
- data/lib/geocoder/lookups/dstk.rb +4 -2
- data/lib/geocoder/lookups/esri.rb +44 -28
- data/lib/geocoder/lookups/freegeoip.rb +11 -7
- data/lib/geocoder/lookups/geocoder_ca.rb +4 -4
- data/lib/geocoder/lookups/geocodio.rb +5 -5
- data/lib/geocoder/lookups/geoportail_lu.rb +7 -7
- data/lib/geocoder/lookups/google.rb +15 -10
- data/lib/geocoder/lookups/google_places_details.rb +11 -17
- data/lib/geocoder/lookups/google_places_search.rb +30 -4
- data/lib/geocoder/lookups/google_premier.rb +14 -0
- data/lib/geocoder/lookups/here.rb +29 -23
- data/lib/geocoder/lookups/ip2location.rb +67 -0
- data/lib/geocoder/lookups/ipapi_com.rb +9 -13
- data/lib/geocoder/lookups/ipdata_co.rb +9 -4
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +11 -29
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/ipstack.rb +11 -12
- data/lib/geocoder/lookups/latlon.rb +5 -6
- data/lib/geocoder/lookups/location_iq.rb +10 -4
- data/lib/geocoder/lookups/mapbox.rb +7 -6
- data/lib/geocoder/lookups/mapquest.rb +4 -5
- data/lib/geocoder/lookups/maxmind.rb +6 -6
- data/lib/geocoder/lookups/maxmind_geoip2.rb +8 -7
- data/lib/geocoder/lookups/maxmind_local.rb +7 -1
- data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/lib/geocoder/lookups/nominatim.rb +4 -4
- data/lib/geocoder/lookups/opencagedata.rb +6 -5
- data/lib/geocoder/lookups/osmnames.rb +57 -0
- data/lib/geocoder/lookups/pelias.rb +8 -9
- data/lib/geocoder/lookups/pickpoint.rb +9 -3
- data/lib/geocoder/lookups/pointpin.rb +10 -9
- data/lib/geocoder/lookups/postcode_anywhere_uk.rb +4 -5
- data/lib/geocoder/lookups/postcodes_io.rb +6 -3
- data/lib/geocoder/lookups/smarty_streets.rb +26 -11
- data/lib/geocoder/lookups/telize.rb +24 -4
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/lookups/test.rb +4 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +7 -8
- data/lib/geocoder/query.rb +14 -0
- data/lib/geocoder/railtie.rb +1 -1
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/baidu.rb +10 -14
- data/lib/geocoder/results/ban_data_gouv_fr.rb +27 -2
- data/lib/geocoder/results/base.rb +13 -1
- data/lib/geocoder/results/bing.rb +1 -1
- data/lib/geocoder/results/db_ip_com.rb +1 -6
- data/lib/geocoder/results/freegeoip.rb +0 -5
- data/lib/geocoder/results/geocoder_ca.rb +3 -3
- data/lib/geocoder/results/geoip2.rb +0 -4
- data/lib/geocoder/results/geoportail_lu.rb +5 -3
- data/lib/geocoder/results/here.rb +4 -1
- data/lib/geocoder/results/ip2location.rb +22 -0
- data/lib/geocoder/results/ipdata_co.rb +0 -5
- data/lib/geocoder/results/ipgeolocation.rb +59 -0
- data/lib/geocoder/results/ipregistry.rb +304 -0
- data/lib/geocoder/results/maxmind.rb +0 -5
- data/lib/geocoder/results/maxmind_local.rb +0 -5
- data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
- data/lib/geocoder/results/nominatim.rb +4 -0
- data/lib/geocoder/results/osmnames.rb +56 -0
- data/lib/geocoder/results/smarty_streets.rb +48 -18
- data/lib/geocoder/results/telize.rb +0 -5
- data/lib/geocoder/results/tencent.rb +72 -0
- data/lib/geocoder/results/test.rb +1 -1
- data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/results/yandex.rb +217 -59
- data/lib/geocoder/sql.rb +4 -4
- data/lib/geocoder/stores/active_record.rb +1 -3
- data/lib/geocoder/util.rb +29 -0
- data/lib/geocoder/version.rb +1 -1
- data/lib/maxmind_database.rb +3 -3
- metadata +27 -23
- data/lib/geocoder/lookups/geocoder_us.rb +0 -43
- data/lib/geocoder/lookups/mapzen.rb +0 -15
- data/lib/geocoder/lookups/okf.rb +0 -44
- data/lib/geocoder/lookups/ovi.rb +0 -62
- data/lib/geocoder/results/geocoder_us.rb +0 -39
- data/lib/geocoder/results/mapzen.rb +0 -5
- data/lib/geocoder/results/okf.rb +0 -106
- data/lib/geocoder/results/ovi.rb +0 -71
- data/lib/hash_recursive_merge.rb +0 -74
data/bin/console
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'geocoder'
|
5
|
+
|
6
|
+
if File.exist?("api_keys.yml")
|
7
|
+
require 'yaml'
|
8
|
+
@api_keys = YAML.load(File.read("api_keys.yml"), symbolize_names: true)
|
9
|
+
Geocoder.configure(@api_keys)
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'irb'
|
13
|
+
IRB.start
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# This class implements a cache with simple delegation to the Redis store, but
|
2
2
|
# when it creates a key/value pair, it also sends an EXPIRE command with a TTL.
|
3
3
|
# It should be fairly simple to do the same thing with Memcached.
|
4
|
+
# Alternatively, this class could inherit from Redis, which would make most
|
5
|
+
# of the below methods unnecessary.
|
4
6
|
class AutoexpireCacheRedis
|
5
7
|
def initialize(store, ttl = 86400)
|
6
8
|
@store = store
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module Geocoder
|
2
|
+
class EastingNorthing
|
3
|
+
attr_reader :easting, :northing, :lat_lng
|
4
|
+
|
5
|
+
def initialize(opts)
|
6
|
+
@easting = opts[:easting]
|
7
|
+
@northing = opts[:northing]
|
8
|
+
|
9
|
+
@lat_lng = to_WGS84(to_osgb_36)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def to_osgb_36
|
15
|
+
osgb_fo = 0.9996012717
|
16
|
+
northing0 = -100_000.0
|
17
|
+
easting0 = 400_000.0
|
18
|
+
phi0 = deg_to_rad(49.0)
|
19
|
+
lambda0 = deg_to_rad(-2.0)
|
20
|
+
a = 6_377_563.396
|
21
|
+
b = 6_356_256.909
|
22
|
+
eSquared = ((a * a) - (b * b)) / (a * a)
|
23
|
+
phi = 0.0
|
24
|
+
lambda = 0.0
|
25
|
+
n = (a - b) / (a + b)
|
26
|
+
m = 0.0
|
27
|
+
phiPrime = ((northing - northing0) / (a * osgb_fo)) + phi0
|
28
|
+
|
29
|
+
while (northing - northing0 - m) >= 0.001
|
30
|
+
m =
|
31
|
+
(b * osgb_fo)\
|
32
|
+
* (((1 + n + ((5.0 / 4.0) * n * n) + ((5.0 / 4.0) * n * n * n))\
|
33
|
+
* (phiPrime - phi0))\
|
34
|
+
- (((3 * n) + (3 * n * n) + ((21.0 / 8.0) * n * n * n))\
|
35
|
+
* Math.sin(phiPrime - phi0)\
|
36
|
+
* Math.cos(phiPrime + phi0))\
|
37
|
+
+ ((((15.0 / 8.0) * n * n) + ((15.0 / 8.0) * n * n * n))\
|
38
|
+
* Math.sin(2.0 * (phiPrime - phi0))\
|
39
|
+
* Math.cos(2.0 * (phiPrime + phi0)))\
|
40
|
+
- (((35.0 / 24.0) * n * n * n)\
|
41
|
+
* Math.sin(3.0 * (phiPrime - phi0))\
|
42
|
+
* Math.cos(3.0 * (phiPrime + phi0))))
|
43
|
+
|
44
|
+
phiPrime += (northing - northing0 - m) / (a * osgb_fo)
|
45
|
+
end
|
46
|
+
|
47
|
+
v = a * osgb_fo * ((1.0 - eSquared * sin_pow_2(phiPrime))**-0.5)
|
48
|
+
rho =
|
49
|
+
a\
|
50
|
+
* osgb_fo\
|
51
|
+
* (1.0 - eSquared)\
|
52
|
+
* ((1.0 - eSquared * sin_pow_2(phiPrime))**-1.5)
|
53
|
+
etaSquared = (v / rho) - 1.0
|
54
|
+
vii = Math.tan(phiPrime) / (2 * rho * v)
|
55
|
+
viii =
|
56
|
+
(Math.tan(phiPrime) / (24.0 * rho * (v**3.0)))\
|
57
|
+
* (5.0\
|
58
|
+
+ (3.0 * tan_pow_2(phiPrime))\
|
59
|
+
+ etaSquared\
|
60
|
+
- (9.0 * tan_pow_2(phiPrime) * etaSquared))
|
61
|
+
ix =
|
62
|
+
(Math.tan(phiPrime) / (720.0 * rho * (v**5.0)))\
|
63
|
+
* (61.0\
|
64
|
+
+ (90.0 * tan_pow_2(phiPrime))\
|
65
|
+
+ (45.0 * tan_pow_2(phiPrime) * tan_pow_2(phiPrime)))
|
66
|
+
x = sec(phiPrime) / v
|
67
|
+
xi =
|
68
|
+
(sec(phiPrime) / (6.0 * v * v * v))\
|
69
|
+
* ((v / rho) + (2 * tan_pow_2(phiPrime)))
|
70
|
+
xiii =
|
71
|
+
(sec(phiPrime) / (120.0 * (v**5.0)))\
|
72
|
+
* (5.0\
|
73
|
+
+ (28.0 * tan_pow_2(phiPrime))\
|
74
|
+
+ (24.0 * tan_pow_2(phiPrime) * tan_pow_2(phiPrime)))
|
75
|
+
xiia =
|
76
|
+
(sec(phiPrime) / (5040.0 * (v**7.0)))\
|
77
|
+
* (61.0\
|
78
|
+
+ (662.0 * tan_pow_2(phiPrime))\
|
79
|
+
+ (1320.0 * tan_pow_2(phiPrime) * tan_pow_2(phiPrime))\
|
80
|
+
+ (720.0\
|
81
|
+
* tan_pow_2(phiPrime)\
|
82
|
+
* tan_pow_2(phiPrime)\
|
83
|
+
* tan_pow_2(phiPrime)))
|
84
|
+
phi =
|
85
|
+
phiPrime\
|
86
|
+
- (vii * ((easting - easting0)**2.0))\
|
87
|
+
+ (viii * ((easting - easting0)**4.0))\
|
88
|
+
- (ix * ((easting - easting0)**6.0))
|
89
|
+
lambda =
|
90
|
+
lambda0\
|
91
|
+
+ (x * (easting - easting0))\
|
92
|
+
- (xi * ((easting - easting0)**3.0))\
|
93
|
+
+ (xiii * ((easting - easting0)**5.0))\
|
94
|
+
- (xiia * ((easting - easting0)**7.0))
|
95
|
+
|
96
|
+
[rad_to_deg(phi), rad_to_deg(lambda)]
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_WGS84(latlng)
|
100
|
+
latitude = latlng[0]
|
101
|
+
longitude = latlng[1]
|
102
|
+
|
103
|
+
a = 6_377_563.396
|
104
|
+
b = 6_356_256.909
|
105
|
+
eSquared = ((a * a) - (b * b)) / (a * a)
|
106
|
+
|
107
|
+
phi = deg_to_rad(latitude)
|
108
|
+
lambda = deg_to_rad(longitude)
|
109
|
+
v = a / Math.sqrt(1 - eSquared * sin_pow_2(phi))
|
110
|
+
h = 0
|
111
|
+
x = (v + h) * Math.cos(phi) * Math.cos(lambda)
|
112
|
+
y = (v + h) * Math.cos(phi) * Math.sin(lambda)
|
113
|
+
z = ((1 - eSquared) * v + h) * Math.sin(phi)
|
114
|
+
|
115
|
+
tx = 446.448
|
116
|
+
ty = -124.157
|
117
|
+
tz = 542.060
|
118
|
+
|
119
|
+
s = -0.0000204894
|
120
|
+
rx = deg_to_rad(0.00004172222)
|
121
|
+
ry = deg_to_rad(0.00006861111)
|
122
|
+
rz = deg_to_rad(0.00023391666)
|
123
|
+
|
124
|
+
xB = tx + (x * (1 + s)) + (-rx * y) + (ry * z)
|
125
|
+
yB = ty + (rz * x) + (y * (1 + s)) + (-rx * z)
|
126
|
+
zB = tz + (-ry * x) + (rx * y) + (z * (1 + s))
|
127
|
+
|
128
|
+
a = 6_378_137.000
|
129
|
+
b = 6_356_752.3141
|
130
|
+
eSquared = ((a * a) - (b * b)) / (a * a)
|
131
|
+
|
132
|
+
lambdaB = rad_to_deg(Math.atan(yB / xB))
|
133
|
+
p = Math.sqrt((xB * xB) + (yB * yB))
|
134
|
+
phiN = Math.atan(zB / (p * (1 - eSquared)))
|
135
|
+
|
136
|
+
(1..10).each do |_i|
|
137
|
+
v = a / Math.sqrt(1 - eSquared * sin_pow_2(phiN))
|
138
|
+
phiN1 = Math.atan((zB + (eSquared * v * Math.sin(phiN))) / p)
|
139
|
+
phiN = phiN1
|
140
|
+
end
|
141
|
+
|
142
|
+
phiB = rad_to_deg(phiN)
|
143
|
+
|
144
|
+
[phiB, lambdaB]
|
145
|
+
end
|
146
|
+
|
147
|
+
def deg_to_rad(degrees)
|
148
|
+
degrees / 180.0 * Math::PI
|
149
|
+
end
|
150
|
+
|
151
|
+
def rad_to_deg(r)
|
152
|
+
(r / Math::PI) * 180
|
153
|
+
end
|
154
|
+
|
155
|
+
def sin_pow_2(x)
|
156
|
+
Math.sin(x) * Math.sin(x)
|
157
|
+
end
|
158
|
+
|
159
|
+
def cos_pow_2(x)
|
160
|
+
Math.cos(x) * Math.cos(x)
|
161
|
+
end
|
162
|
+
|
163
|
+
def tan_pow_2(x)
|
164
|
+
Math.tan(x) * Math.tan(x)
|
165
|
+
end
|
166
|
+
|
167
|
+
def sec(x)
|
168
|
+
1.0 / Math.cos(x)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Geocoder.configure(
|
2
2
|
# Geocoding options
|
3
3
|
# timeout: 3, # geocoding service timeout (secs)
|
4
|
-
# lookup: :
|
4
|
+
# lookup: :nominatim, # name of geocoding service (symbol)
|
5
5
|
# ip_lookup: :ipinfo_io, # name of IP address geocoding service (symbol)
|
6
6
|
# language: :en, # ISO-639 language code
|
7
7
|
# use_https: false, # use HTTPS for lookup requests? (if supported)
|
data/lib/geocoder/cache.rb
CHANGED
@@ -18,6 +18,8 @@ module Geocoder
|
|
18
18
|
when store.respond_to?(:read)
|
19
19
|
store.read key_for(url)
|
20
20
|
end
|
21
|
+
rescue => e
|
22
|
+
warn "Geocoder cache read error: #{e}"
|
21
23
|
end
|
22
24
|
|
23
25
|
##
|
@@ -32,6 +34,8 @@ module Geocoder
|
|
32
34
|
when store.respond_to?(:write)
|
33
35
|
store.write key_for(url), value
|
34
36
|
end
|
37
|
+
rescue => e
|
38
|
+
warn "Geocoder cache write error: #{e}"
|
35
39
|
end
|
36
40
|
|
37
41
|
##
|
@@ -154,7 +154,7 @@ module Geocoder
|
|
154
154
|
# Translate a bearing (float) into a compass direction (string, eg "North").
|
155
155
|
#
|
156
156
|
def compass_point(bearing, points = COMPASS_POINTS)
|
157
|
-
seg_size = 360 / points.size
|
157
|
+
seg_size = 360.0 / points.size
|
158
158
|
points[((bearing + (seg_size / 2)) % 360) / seg_size]
|
159
159
|
end
|
160
160
|
|
data/lib/geocoder/cli.rb
CHANGED
@@ -97,7 +97,7 @@ module Geocoder
|
|
97
97
|
end
|
98
98
|
|
99
99
|
if (result = Geocoder.search(query).first)
|
100
|
-
|
100
|
+
nominatim = Geocoder::Lookup.get(:nominatim)
|
101
101
|
lines = [
|
102
102
|
["Latitude", result.latitude],
|
103
103
|
["Longitude", result.longitude],
|
@@ -106,7 +106,7 @@ module Geocoder
|
|
106
106
|
["State/province", result.state],
|
107
107
|
["Postal code", result.postal_code],
|
108
108
|
["Country", result.country],
|
109
|
-
["
|
109
|
+
["Map", nominatim.map_link_url(result.coordinates)],
|
110
110
|
]
|
111
111
|
lines.each do |line|
|
112
112
|
out << (line[0] + ": ").ljust(18) + line[1].to_s + "\n"
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'singleton'
|
2
2
|
require 'geocoder/configuration_hash'
|
3
|
+
require 'geocoder/util'
|
3
4
|
|
4
5
|
module Geocoder
|
5
6
|
|
@@ -85,7 +86,7 @@ module Geocoder
|
|
85
86
|
end
|
86
87
|
|
87
88
|
def configure(options)
|
88
|
-
@data
|
89
|
+
Util.recursive_hash_merge(@data, options)
|
89
90
|
end
|
90
91
|
|
91
92
|
def initialize # :nodoc
|
@@ -97,7 +98,7 @@ module Geocoder
|
|
97
98
|
|
98
99
|
# geocoding options
|
99
100
|
@data[:timeout] = 3 # geocoding service timeout (secs)
|
100
|
-
@data[:lookup] = :
|
101
|
+
@data[:lookup] = :nominatim # name of street address geocoding service (symbol)
|
101
102
|
@data[:ip_lookup] = :ipinfo_io # name of IP address geocoding service (symbol)
|
102
103
|
@data[:language] = :en # ISO-639 language code
|
103
104
|
@data[:http_headers] = {} # HTTP headers for lookup
|
@@ -1,11 +1,11 @@
|
|
1
|
-
require 'hash_recursive_merge'
|
2
|
-
|
3
1
|
module Geocoder
|
4
2
|
class ConfigurationHash < Hash
|
5
|
-
include HashRecursiveMerge
|
6
|
-
|
7
3
|
def method_missing(meth, *args, &block)
|
8
4
|
has_key?(meth) ? self[meth] : super
|
9
5
|
end
|
6
|
+
|
7
|
+
def respond_to_missing?(meth, include_private = false)
|
8
|
+
has_key?(meth) || super
|
9
|
+
end
|
10
10
|
end
|
11
11
|
end
|
data/lib/geocoder/exceptions.rb
CHANGED
data/lib/geocoder/ip_address.rb
CHANGED
@@ -1,13 +1,27 @@
|
|
1
1
|
require 'resolv'
|
2
2
|
module Geocoder
|
3
3
|
class IpAddress < String
|
4
|
+
PRIVATE_IPS = [
|
5
|
+
'10.0.0.0/8',
|
6
|
+
'172.16.0.0/12',
|
7
|
+
'192.168.0.0/16',
|
8
|
+
].map { |ip| IPAddr.new(ip) }.freeze
|
9
|
+
|
10
|
+
def internal?
|
11
|
+
loopback? || private?
|
12
|
+
end
|
4
13
|
|
5
14
|
def loopback?
|
6
|
-
valid? and (self == "0.0.0.0" or self.match(/\A127\./) or self == "::1")
|
15
|
+
valid? and !!(self == "0.0.0.0" or self.match(/\A127\./) or self == "::1")
|
16
|
+
end
|
17
|
+
|
18
|
+
def private?
|
19
|
+
valid? && PRIVATE_IPS.any? { |ip| ip.include?(self) }
|
7
20
|
end
|
8
21
|
|
9
22
|
def valid?
|
10
|
-
|
23
|
+
ip = self[/(?<=\[)(.*?)(?=\])/] || self
|
24
|
+
!!((ip =~ Resolv::IPv4::Regex) || (ip =~ Resolv::IPv6::Regex))
|
11
25
|
end
|
12
26
|
end
|
13
27
|
end
|
data/lib/geocoder/lookup.rb
CHANGED
@@ -32,28 +32,28 @@ module Geocoder
|
|
32
32
|
:google_places_search,
|
33
33
|
:bing,
|
34
34
|
:geocoder_ca,
|
35
|
-
:geocoder_us,
|
36
35
|
:yandex,
|
36
|
+
:nationaal_georegister_nl,
|
37
37
|
:nominatim,
|
38
38
|
:mapbox,
|
39
39
|
:mapquest,
|
40
|
-
:
|
40
|
+
:uk_ordnance_survey_names,
|
41
41
|
:opencagedata,
|
42
|
-
:ovi,
|
43
42
|
:pelias,
|
44
43
|
:pickpoint,
|
45
44
|
:here,
|
46
45
|
:baidu,
|
46
|
+
:tencent,
|
47
47
|
:geocodio,
|
48
48
|
:smarty_streets,
|
49
|
-
:okf,
|
50
49
|
:postcode_anywhere_uk,
|
51
50
|
:postcodes_io,
|
52
51
|
:geoportail_lu,
|
53
52
|
:ban_data_gouv_fr,
|
54
53
|
:test,
|
55
54
|
:latlon,
|
56
|
-
:amap
|
55
|
+
:amap,
|
56
|
+
:osmnames
|
57
57
|
]
|
58
58
|
end
|
59
59
|
|
@@ -63,6 +63,7 @@ module Geocoder
|
|
63
63
|
def ip_services
|
64
64
|
@ip_services ||= [
|
65
65
|
:baidu_ip,
|
66
|
+
:abstract_api,
|
66
67
|
:freegeoip,
|
67
68
|
:geoip2,
|
68
69
|
:maxmind,
|
@@ -71,10 +72,13 @@ module Geocoder
|
|
71
72
|
:pointpin,
|
72
73
|
:maxmind_geoip2,
|
73
74
|
:ipinfo_io,
|
75
|
+
:ipregistry,
|
74
76
|
:ipapi_com,
|
75
77
|
:ipdata_co,
|
76
78
|
:db_ip_com,
|
77
79
|
:ipstack,
|
80
|
+
:ip2location,
|
81
|
+
:ipgeolocation
|
78
82
|
]
|
79
83
|
end
|
80
84
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'geocoder/lookups/base'
|
4
|
+
require 'geocoder/results/abstract_api'
|
5
|
+
|
6
|
+
module Geocoder::Lookup
|
7
|
+
class AbstractApi < Base
|
8
|
+
|
9
|
+
def name
|
10
|
+
"Abstract API"
|
11
|
+
end
|
12
|
+
|
13
|
+
def required_api_key_parts
|
14
|
+
['api_key']
|
15
|
+
end
|
16
|
+
|
17
|
+
def supported_protocols
|
18
|
+
[:https]
|
19
|
+
end
|
20
|
+
|
21
|
+
private # ---------------------------------------------------------------
|
22
|
+
|
23
|
+
def base_query_url(query)
|
24
|
+
"#{protocol}://ipgeolocation.abstractapi.com/v1/?"
|
25
|
+
end
|
26
|
+
|
27
|
+
def query_url_params(query)
|
28
|
+
params = {api_key: configuration.api_key}
|
29
|
+
|
30
|
+
ip_address = query.sanitized_text
|
31
|
+
if ip_address.is_a?(String) && ip_address.length > 0
|
32
|
+
params[:ip_address] = ip_address
|
33
|
+
end
|
34
|
+
|
35
|
+
params.merge(super)
|
36
|
+
end
|
37
|
+
|
38
|
+
def results(query, reverse = false)
|
39
|
+
if doc = fetch_data(query)
|
40
|
+
[doc]
|
41
|
+
else
|
42
|
+
[]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -12,13 +12,17 @@ module Geocoder::Lookup
|
|
12
12
|
["key"]
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
"http://restapi.amap.com/v3/geocode/#{path}?" + url_query_string(query)
|
15
|
+
def supported_protocols
|
16
|
+
[:http]
|
18
17
|
end
|
19
18
|
|
20
19
|
private # ---------------------------------------------------------------
|
21
20
|
|
21
|
+
def base_query_url(query)
|
22
|
+
path = query.reverse_geocode? ? 'regeo' : 'geo'
|
23
|
+
"http://restapi.amap.com/v3/geocode/#{path}?"
|
24
|
+
end
|
25
|
+
|
22
26
|
def results(query, reverse = false)
|
23
27
|
return [] unless doc = fetch_data(query)
|
24
28
|
case [doc['status'], doc['info']]
|