geocoder 1.5.0 → 1.6.2

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.
Files changed (59) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +29 -2
  3. data/LICENSE +1 -1
  4. data/README.md +15 -17
  5. data/bin/console +7 -0
  6. data/examples/autoexpire_cache_redis.rb +2 -0
  7. data/lib/easting_northing.rb +171 -0
  8. data/lib/geocoder/calculations.rb +1 -1
  9. data/lib/geocoder/ip_address.rb +13 -0
  10. data/lib/geocoder/lookup.rb +8 -4
  11. data/lib/geocoder/lookups/baidu_ip.rb +1 -1
  12. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +13 -0
  13. data/lib/geocoder/lookups/base.rb +7 -2
  14. data/lib/geocoder/lookups/bing.rb +2 -1
  15. data/lib/geocoder/lookups/esri.rb +38 -13
  16. data/lib/geocoder/lookups/freegeoip.rb +7 -7
  17. data/lib/geocoder/lookups/here.rb +28 -22
  18. data/lib/geocoder/lookups/ip2location.rb +7 -14
  19. data/lib/geocoder/lookups/ipapi_com.rb +2 -1
  20. data/lib/geocoder/lookups/ipdata_co.rb +5 -4
  21. data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  22. data/lib/geocoder/lookups/ipinfo_io.rb +2 -11
  23. data/lib/geocoder/lookups/ipregistry.rb +68 -0
  24. data/lib/geocoder/lookups/ipstack.rb +2 -2
  25. data/lib/geocoder/lookups/maxmind.rb +2 -2
  26. data/lib/geocoder/lookups/maxmind_geoip2.rb +4 -7
  27. data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
  28. data/lib/geocoder/lookups/osmnames.rb +57 -0
  29. data/lib/geocoder/lookups/pelias.rb +2 -3
  30. data/lib/geocoder/lookups/pickpoint.rb +1 -1
  31. data/lib/geocoder/lookups/pointpin.rb +3 -3
  32. data/lib/geocoder/lookups/smarty_streets.rb +13 -3
  33. data/lib/geocoder/lookups/telize.rb +2 -2
  34. data/lib/geocoder/lookups/tencent.rb +59 -0
  35. data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
  36. data/lib/geocoder/lookups/yandex.rb +2 -2
  37. data/lib/geocoder/query.rb +14 -0
  38. data/lib/geocoder/railtie.rb +1 -1
  39. data/lib/geocoder/results/baidu.rb +0 -4
  40. data/lib/geocoder/results/ban_data_gouv_fr.rb +1 -1
  41. data/lib/geocoder/results/here.rb +4 -1
  42. data/lib/geocoder/results/ipgeolocation.rb +59 -0
  43. data/lib/geocoder/results/ipregistry.rb +308 -0
  44. data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
  45. data/lib/geocoder/results/osmnames.rb +56 -0
  46. data/lib/geocoder/results/smarty_streets.rb +48 -18
  47. data/lib/geocoder/results/tencent.rb +72 -0
  48. data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
  49. data/lib/geocoder/results/yandex.rb +217 -59
  50. data/lib/geocoder/sql.rb +4 -4
  51. data/lib/geocoder/stores/active_record.rb +1 -1
  52. data/lib/geocoder/version.rb +1 -1
  53. data/lib/hash_recursive_merge.rb +1 -2
  54. data/lib/maxmind_database.rb +3 -3
  55. metadata +18 -13
  56. data/lib/geocoder/lookups/geocoder_us.rb +0 -51
  57. data/lib/geocoder/lookups/mapzen.rb +0 -15
  58. data/lib/geocoder/results/geocoder_us.rb +0 -39
  59. data/lib/geocoder/results/mapzen.rb +0 -5
@@ -53,7 +53,8 @@ module Geocoder::Lookup
53
53
 
54
54
  def query_url_params(query)
55
55
  {
56
- key: configuration.api_key
56
+ key: configuration.api_key,
57
+ language: (query.language || configuration.language)
57
58
  }.merge(super)
58
59
  end
59
60
 
@@ -40,31 +40,56 @@ module Geocoder::Lookup
40
40
  else
41
41
  params[:text] = query.sanitized_text
42
42
  end
43
- params[:token] = token
44
- params[:forStorage] = configuration[:for_storage] if configuration[:for_storage]
43
+
44
+ params[:token] = token(query)
45
+
46
+ if for_storage_value = for_storage(query)
47
+ params[:forStorage] = for_storage_value
48
+ end
45
49
  params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
46
50
  params.merge(super)
47
51
  end
48
52
 
49
- def token
50
- create_and_save_token! if !valid_token_configured? and configuration.api_key
51
- configuration[:token].to_s unless configuration[:token].nil?
53
+ def for_storage(query)
54
+ if query.options.has_key?(:for_storage)
55
+ query.options[:for_storage]
56
+ else
57
+ configuration[:for_storage]
58
+ end
59
+ end
60
+
61
+ def token(query)
62
+ token_instance = if query.options[:token]
63
+ query.options[:token]
64
+ else
65
+ configuration[:token]
66
+ end
67
+
68
+ if !valid_token_configured?(token_instance) && configuration.api_key
69
+ token_instance = create_and_save_token!(query)
70
+ end
71
+
72
+ token_instance.to_s unless token_instance.nil?
52
73
  end
53
74
 
54
- def valid_token_configured?
55
- !configuration[:token].nil? and configuration[:token].active?
75
+ def valid_token_configured?(token_instance)
76
+ !token_instance.nil? && token_instance.active?
56
77
  end
57
78
 
58
- def create_and_save_token!
59
- save_token!(create_token)
79
+ def create_and_save_token!(query)
80
+ token_instance = create_token
81
+
82
+ if query.options[:token]
83
+ query.options[:token] = token_instance
84
+ else
85
+ Geocoder.merge_into_lookup_config(:esri, token: token_instance)
86
+ end
87
+
88
+ token_instance
60
89
  end
61
90
 
62
91
  def create_token
63
92
  Geocoder::EsriToken.generate_token(*configuration.api_key)
64
93
  end
65
-
66
- def save_token!(token_instance)
67
- Geocoder.merge_into_lookup_config(:esri, token: token_instance)
68
- end
69
94
  end
70
95
  end
@@ -7,10 +7,10 @@ module Geocoder::Lookup
7
7
  def name
8
8
  "FreeGeoIP"
9
9
  end
10
-
10
+
11
11
  def supported_protocols
12
12
  if configuration[:host]
13
- [:http, :https]
13
+ [:https]
14
14
  else
15
15
  # use https for default host
16
16
  [:https]
@@ -32,8 +32,8 @@ module Geocoder::Lookup
32
32
  end
33
33
 
34
34
  def results(query)
35
- # don't look up a loopback address, just return the stored result
36
- return [reserved_result(query.text)] if query.loopback_ip_address?
35
+ # don't look up a loopback or private address, just return the stored result
36
+ return [reserved_result(query.text)] if query.internal_ip_address?
37
37
  # note: Freegeoip.net returns plain text "Not Found" on bad request
38
38
  (doc = fetch_data(query)) ? [doc] : []
39
39
  end
@@ -44,8 +44,8 @@ module Geocoder::Lookup
44
44
  "city" => "",
45
45
  "region_code" => "",
46
46
  "region_name" => "",
47
- "metrocode" => "",
48
- "zipcode" => "",
47
+ "metro_code" => "",
48
+ "zip_code" => "",
49
49
  "latitude" => "0",
50
50
  "longitude" => "0",
51
51
  "country_name" => "Reserved",
@@ -54,7 +54,7 @@ module Geocoder::Lookup
54
54
  end
55
55
 
56
56
  def host
57
- configuration[:host] || "freegeoip.net"
57
+ configuration[:host] || "freegeoip.app"
58
58
  end
59
59
  end
60
60
  end
@@ -9,13 +9,17 @@ module Geocoder::Lookup
9
9
  end
10
10
 
11
11
  def required_api_key_parts
12
- ["app_id", "app_code"]
12
+ ['api_key']
13
+ end
14
+
15
+ def supported_protocols
16
+ [:https]
13
17
  end
14
18
 
15
19
  private # ---------------------------------------------------------------
16
20
 
17
21
  def base_query_url(query)
18
- "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.api.here.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
22
+ "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.ls.hereapi.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
19
23
  end
20
24
 
21
25
  def results(query)
@@ -28,34 +32,36 @@ module Geocoder::Lookup
28
32
  []
29
33
  end
30
34
 
31
- def query_url_params(query)
35
+ def query_url_here_options(query, reverse_geocode)
32
36
  options = {
33
- :gen=>4,
34
- :app_id=>api_key,
35
- :app_code=>api_code
37
+ gen: 9,
38
+ apikey: configuration.api_key,
39
+ language: (query.language || configuration.language)
36
40
  }
41
+ if reverse_geocode
42
+ options[:mode] = :retrieveAddresses
43
+ return options
44
+ end
37
45
 
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
- )
46
+ unless (country = query.options[:country]).nil?
47
+ options[:country] = country
47
48
  end
48
- end
49
49
 
50
- def api_key
51
- if a=configuration.api_key
52
- return a.first if a.is_a?(Array)
50
+ unless (mapview = query.options[:bounds]).nil?
51
+ options[:mapview] = mapview.map{ |point| "%f,%f" % point }.join(';')
53
52
  end
53
+ options
54
54
  end
55
55
 
56
- def api_code
57
- if a=configuration.api_key
58
- return a.last if a.is_a?(Array)
56
+ def query_url_params(query)
57
+ if query.reverse_geocode?
58
+ super.merge(query_url_here_options(query, true)).merge(
59
+ prox: query.sanitized_text
60
+ )
61
+ else
62
+ super.merge(query_url_here_options(query, false)).merge(
63
+ searchtext: query.sanitized_text
64
+ )
59
65
  end
60
66
  end
61
67
  end
@@ -19,15 +19,16 @@ module Geocoder::Lookup
19
19
  end
20
20
 
21
21
  def query_url_params(query)
22
- {
23
- key: configuration.api_key ? configuration.api_key : "demo",
24
- format: "json",
25
- ip: query.sanitized_text
26
- }.merge(super)
22
+ params = super
23
+ if configuration.has_key?(:package)
24
+ params.merge!(package: configuration[:package])
25
+ end
26
+ params
27
27
  end
28
28
 
29
29
  def results(query)
30
- return [reserved_result(query.text)] if query.loopback_ip_address?
30
+ # don't look up a loopback or private address, just return the stored result
31
+ return [reserved_result(query.text)] if query.internal_ip_address?
31
32
  return [] unless doc = fetch_data(query)
32
33
  if doc["response"] == "INVALID ACCOUNT"
33
34
  raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "INVALID ACCOUNT")
@@ -62,13 +63,5 @@ module Geocoder::Lookup
62
63
  }
63
64
  end
64
65
 
65
- def query_url_params(query)
66
- params = super
67
- if configuration.has_key?(:package)
68
- params.merge!(package: configuration[:package])
69
- end
70
- params
71
- end
72
-
73
66
  end
74
67
  end
@@ -34,7 +34,8 @@ module Geocoder::Lookup
34
34
  end
35
35
 
36
36
  def results(query)
37
- return [reserved_result(query.text)] if query.loopback_ip_address?
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?
38
39
 
39
40
  return [] unless doc = fetch_data(query)
40
41
 
@@ -13,7 +13,9 @@ module Geocoder::Lookup
13
13
  end
14
14
 
15
15
  def query_url(query)
16
- "#{protocol}://#{host}/#{query.sanitized_text}"
16
+ # Ipdata.co requires that the API key be sent as a query parameter.
17
+ # It no longer supports API keys sent as headers.
18
+ "#{protocol}://#{host}/#{query.sanitized_text}?api-key=#{configuration.api_key}"
17
19
  end
18
20
 
19
21
  private # ---------------------------------------------------------------
@@ -23,9 +25,8 @@ module Geocoder::Lookup
23
25
  end
24
26
 
25
27
  def results(query)
26
- Geocoder.configure(:ipdata_co => {:http_headers => { "api-key" => configuration.api_key }}) if configuration.api_key
27
- # don't look up a loopback address, just return the stored result
28
- return [reserved_result(query.text)] if query.loopback_ip_address?
28
+ # don't look up a loopback or private address, just return the stored result
29
+ return [reserved_result(query.text)] if query.internal_ip_address?
29
30
  # note: Ipdata.co returns plain text on bad request
30
31
  (doc = fetch_data(query)) ? [doc] : []
31
32
  end
@@ -0,0 +1,51 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/ipgeolocation'
3
+
4
+
5
+ module Geocoder::Lookup
6
+ class Ipgeolocation < Base
7
+
8
+ ERROR_CODES = {
9
+ 400 => Geocoder::RequestDenied, # subscription is paused
10
+ 401 => Geocoder::InvalidApiKey, # missing/invalid API key
11
+ 403 => Geocoder::InvalidRequest, # invalid IP address
12
+ 404 => Geocoder::InvalidRequest, # not found
13
+ 423 => Geocoder::InvalidRequest # bogon/reserved IP address
14
+ }
15
+ ERROR_CODES.default = Geocoder::Error
16
+
17
+ def name
18
+ "Ipgeolocation"
19
+ end
20
+
21
+ def supported_protocols
22
+ [:https]
23
+ end
24
+
25
+ private # ----------------------------------------------------------------
26
+
27
+ def base_query_url(query)
28
+ "#{protocol}://api.ipgeolocation.io/ipgeo?"
29
+ end
30
+ def query_url_params(query)
31
+ {
32
+ ip: query.sanitized_text,
33
+ apiKey: configuration.api_key
34
+ }.merge(super)
35
+ end
36
+
37
+ def results(query)
38
+ # don't look up a loopback or private address, just return the stored result
39
+ return [reserved_result(query.text)] if query.internal_ip_address?
40
+ [fetch_data(query)]
41
+ end
42
+
43
+ def reserved_result(ip)
44
+ {
45
+ "ip" => ip,
46
+ "country_name" => "Reserved",
47
+ "country_code2" => "RD"
48
+ }
49
+ end
50
+ end
51
+ end
@@ -8,15 +8,6 @@ module Geocoder::Lookup
8
8
  "Ipinfo.io"
9
9
  end
10
10
 
11
- # HTTPS available only for paid plans
12
- def supported_protocols
13
- if configuration.api_key
14
- [:http, :https]
15
- else
16
- [:http]
17
- end
18
- end
19
-
20
11
  private # ---------------------------------------------------------------
21
12
 
22
13
  def base_query_url(query)
@@ -26,8 +17,8 @@ module Geocoder::Lookup
26
17
  end
27
18
 
28
19
  def results(query)
29
- # don't look up a loopback address, just return the stored result
30
- return [reserved_result(query.text)] if query.loopback_ip_address?
20
+ # don't look up a loopback or private address, just return the stored result
21
+ return [reserved_result(query.text)] if query.internal_ip_address?
31
22
 
32
23
  if !(doc = fetch_data(query)).is_a?(Hash) or doc['error']
33
24
  []
@@ -0,0 +1,68 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/ipregistry'
3
+
4
+ module Geocoder::Lookup
5
+ class Ipregistry < Base
6
+
7
+ ERROR_CODES = {
8
+ 400 => Geocoder::InvalidRequest,
9
+ 401 => Geocoder::InvalidRequest,
10
+ 402 => Geocoder::OverQueryLimitError,
11
+ 403 => Geocoder::InvalidApiKey,
12
+ 451 => Geocoder::RequestDenied,
13
+ 500 => Geocoder::Error
14
+ }
15
+ ERROR_CODES.default = Geocoder::Error
16
+
17
+ def name
18
+ "Ipregistry"
19
+ end
20
+
21
+ def supported_protocols
22
+ [:https, :http]
23
+ end
24
+
25
+ private
26
+
27
+ def base_query_url(query)
28
+ "#{protocol}://#{host}/#{query.sanitized_text}?"
29
+ end
30
+
31
+ def cache_key(query)
32
+ query_url(query)
33
+ end
34
+
35
+ def host
36
+ configuration[:host] || "api.ipregistry.co"
37
+ end
38
+
39
+ def query_url_params(query)
40
+ {
41
+ key: configuration.api_key
42
+ }.merge(super)
43
+ end
44
+
45
+ def results(query)
46
+ # don't look up a loopback or private address, just return the stored result
47
+ return [reserved_result(query.text)] if query.internal_ip_address?
48
+
49
+ return [] unless (doc = fetch_data(query))
50
+
51
+ if (error = doc['error'])
52
+ code = error['code']
53
+ msg = error['message']
54
+ raise_error(ERROR_CODES[code], msg ) || Geocoder.log(:warn, "Ipregistry API error: #{msg}")
55
+ return []
56
+ end
57
+ [doc]
58
+ end
59
+
60
+ def reserved_result(ip)
61
+ {
62
+ "ip" => ip,
63
+ "country_name" => "Reserved",
64
+ "country_code" => "RD"
65
+ }
66
+ end
67
+ end
68
+ end
@@ -34,8 +34,8 @@ module Geocoder::Lookup
34
34
  end
35
35
 
36
36
  def results(query)
37
- # don't look up a loopback address, just return the stored result
38
- return [reserved_result(query.text)] if query.loopback_ip_address?
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?
39
39
 
40
40
  return [] unless doc = fetch_data(query)
41
41
 
@@ -57,8 +57,8 @@ module Geocoder::Lookup
57
57
  end
58
58
 
59
59
  def results(query)
60
- # don't look up a loopback address, just return the stored result
61
- return [reserved_result] if query.loopback_ip_address?
60
+ # don't look up a loopback or private address, just return the stored result
61
+ return [reserved_result] if query.internal_ip_address?
62
62
  doc = fetch_data(query)
63
63
  if doc and doc.is_a?(Array)
64
64
  if !data_contains_error?(doc)
@@ -32,11 +32,7 @@ module Geocoder::Lookup
32
32
  return s
33
33
  else
34
34
  raise(
35
- Geocoder::ConfigurationError,
36
- "When using MaxMind GeoIP2 you MUST specify a service name and basic_auth: " +
37
- "Geocoder.configure(:maxmind_geoip2 => {:service => ...}, " +
38
- ":basic_auth => {:user ..., :password => ...}), " +
39
- "where service is one of: #{services.inspect}"
35
+ Geocoder::ConfigurationError, "When using MaxMind GeoIP2 you must specify a service and credentials: Geocoder.configure(maxmind_geoip2: {service: ..., basic_auth: {user: ..., password: ...}}), where service is one of: #{services.inspect}"
40
36
  )
41
37
  end
42
38
  end
@@ -57,8 +53,9 @@ module Geocoder::Lookup
57
53
  end
58
54
 
59
55
  def results(query)
60
- # don't look up a loopback address
61
- return [] if query.loopback_ip_address?
56
+ # don't look up a loopback or private address, just return the stored result
57
+ return [] if query.internal_ip_address?
58
+
62
59
  doc = fetch_data(query)
63
60
  if doc
64
61
  if !data_contains_error?(doc)