broken-geocoder 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +467 -0
  3. data/LICENSE +20 -0
  4. data/README.md +1193 -0
  5. data/bin/geocode +5 -0
  6. data/examples/autoexpire_cache_dalli.rb +62 -0
  7. data/examples/autoexpire_cache_redis.rb +28 -0
  8. data/examples/cache_bypass.rb +48 -0
  9. data/examples/reverse_geocode_job.rb +40 -0
  10. data/lib/generators/geocoder/config/config_generator.rb +14 -0
  11. data/lib/generators/geocoder/config/templates/initializer.rb +21 -0
  12. data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +28 -0
  13. data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +28 -0
  14. data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
  15. data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
  16. data/lib/geocoder.rb +48 -0
  17. data/lib/geocoder/cache.rb +90 -0
  18. data/lib/geocoder/calculations.rb +431 -0
  19. data/lib/geocoder/cli.rb +121 -0
  20. data/lib/geocoder/configuration.rb +129 -0
  21. data/lib/geocoder/configuration_hash.rb +11 -0
  22. data/lib/geocoder/esri_token.rb +38 -0
  23. data/lib/geocoder/exceptions.rb +37 -0
  24. data/lib/geocoder/ip_address.rb +13 -0
  25. data/lib/geocoder/kernel_logger.rb +25 -0
  26. data/lib/geocoder/logger.rb +47 -0
  27. data/lib/geocoder/lookup.rb +110 -0
  28. data/lib/geocoder/lookups/baidu.rb +59 -0
  29. data/lib/geocoder/lookups/baidu_ip.rb +59 -0
  30. data/lib/geocoder/lookups/base.rb +325 -0
  31. data/lib/geocoder/lookups/bing.rb +80 -0
  32. data/lib/geocoder/lookups/dstk.rb +20 -0
  33. data/lib/geocoder/lookups/esri.rb +64 -0
  34. data/lib/geocoder/lookups/freegeoip.rb +51 -0
  35. data/lib/geocoder/lookups/geocoder_ca.rb +53 -0
  36. data/lib/geocoder/lookups/geocoder_us.rb +43 -0
  37. data/lib/geocoder/lookups/geocodio.rb +42 -0
  38. data/lib/geocoder/lookups/geoip2.rb +45 -0
  39. data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
  40. data/lib/geocoder/lookups/google.rb +91 -0
  41. data/lib/geocoder/lookups/google_places_details.rb +50 -0
  42. data/lib/geocoder/lookups/google_premier.rb +47 -0
  43. data/lib/geocoder/lookups/here.rb +62 -0
  44. data/lib/geocoder/lookups/ipapi_com.rb +86 -0
  45. data/lib/geocoder/lookups/ipinfo_io.rb +55 -0
  46. data/lib/geocoder/lookups/latlon.rb +59 -0
  47. data/lib/geocoder/lookups/mapbox.rb +53 -0
  48. data/lib/geocoder/lookups/mapquest.rb +59 -0
  49. data/lib/geocoder/lookups/mapzen.rb +15 -0
  50. data/lib/geocoder/lookups/maxmind.rb +90 -0
  51. data/lib/geocoder/lookups/maxmind_geoip2.rb +69 -0
  52. data/lib/geocoder/lookups/maxmind_local.rb +65 -0
  53. data/lib/geocoder/lookups/nominatim.rb +52 -0
  54. data/lib/geocoder/lookups/okf.rb +44 -0
  55. data/lib/geocoder/lookups/opencagedata.rb +58 -0
  56. data/lib/geocoder/lookups/ovi.rb +62 -0
  57. data/lib/geocoder/lookups/pelias.rb +64 -0
  58. data/lib/geocoder/lookups/pointpin.rb +68 -0
  59. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +51 -0
  60. data/lib/geocoder/lookups/smarty_streets.rb +50 -0
  61. data/lib/geocoder/lookups/telize.rb +55 -0
  62. data/lib/geocoder/lookups/test.rb +44 -0
  63. data/lib/geocoder/lookups/yandex.rb +58 -0
  64. data/lib/geocoder/models/active_record.rb +50 -0
  65. data/lib/geocoder/models/base.rb +39 -0
  66. data/lib/geocoder/models/mongo_base.rb +62 -0
  67. data/lib/geocoder/models/mongo_mapper.rb +26 -0
  68. data/lib/geocoder/models/mongoid.rb +32 -0
  69. data/lib/geocoder/query.rb +111 -0
  70. data/lib/geocoder/railtie.rb +26 -0
  71. data/lib/geocoder/request.rb +83 -0
  72. data/lib/geocoder/results/baidu.rb +79 -0
  73. data/lib/geocoder/results/baidu_ip.rb +62 -0
  74. data/lib/geocoder/results/base.rb +67 -0
  75. data/lib/geocoder/results/bing.rb +52 -0
  76. data/lib/geocoder/results/dstk.rb +6 -0
  77. data/lib/geocoder/results/esri.rb +75 -0
  78. data/lib/geocoder/results/freegeoip.rb +45 -0
  79. data/lib/geocoder/results/geocoder_ca.rb +60 -0
  80. data/lib/geocoder/results/geocoder_us.rb +39 -0
  81. data/lib/geocoder/results/geocodio.rb +70 -0
  82. data/lib/geocoder/results/geoip2.rb +62 -0
  83. data/lib/geocoder/results/geoportail_lu.rb +69 -0
  84. data/lib/geocoder/results/google.rb +139 -0
  85. data/lib/geocoder/results/google_places_details.rb +35 -0
  86. data/lib/geocoder/results/google_premier.rb +6 -0
  87. data/lib/geocoder/results/here.rb +71 -0
  88. data/lib/geocoder/results/ipapi_com.rb +45 -0
  89. data/lib/geocoder/results/ipinfo_io.rb +48 -0
  90. data/lib/geocoder/results/latlon.rb +71 -0
  91. data/lib/geocoder/results/mapbox.rb +47 -0
  92. data/lib/geocoder/results/mapquest.rb +48 -0
  93. data/lib/geocoder/results/mapzen.rb +5 -0
  94. data/lib/geocoder/results/maxmind.rb +135 -0
  95. data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
  96. data/lib/geocoder/results/maxmind_local.rb +49 -0
  97. data/lib/geocoder/results/nominatim.rb +99 -0
  98. data/lib/geocoder/results/okf.rb +106 -0
  99. data/lib/geocoder/results/opencagedata.rb +90 -0
  100. data/lib/geocoder/results/ovi.rb +71 -0
  101. data/lib/geocoder/results/pelias.rb +58 -0
  102. data/lib/geocoder/results/pointpin.rb +40 -0
  103. data/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
  104. data/lib/geocoder/results/smarty_streets.rb +106 -0
  105. data/lib/geocoder/results/telize.rb +45 -0
  106. data/lib/geocoder/results/test.rb +33 -0
  107. data/lib/geocoder/results/yandex.rb +92 -0
  108. data/lib/geocoder/sql.rb +107 -0
  109. data/lib/geocoder/stores/active_record.rb +305 -0
  110. data/lib/geocoder/stores/base.rb +116 -0
  111. data/lib/geocoder/stores/mongo_base.rb +58 -0
  112. data/lib/geocoder/stores/mongo_mapper.rb +13 -0
  113. data/lib/geocoder/stores/mongoid.rb +13 -0
  114. data/lib/geocoder/version.rb +3 -0
  115. data/lib/hash_recursive_merge.rb +74 -0
  116. data/lib/maxmind_database.rb +109 -0
  117. data/lib/tasks/geocoder.rake +38 -0
  118. data/lib/tasks/maxmind.rake +73 -0
  119. metadata +167 -0
@@ -0,0 +1,20 @@
1
+ # More information about the Data Science Toolkit can be found at:
2
+ # http://www.datasciencetoolkit.org/. The provided APIs mimic the
3
+ # Google geocoding api.
4
+
5
+ require 'geocoder/lookups/google'
6
+ require 'geocoder/results/dstk'
7
+
8
+ module Geocoder::Lookup
9
+ class Dstk < Google
10
+
11
+ def name
12
+ "Data Science Toolkit"
13
+ end
14
+
15
+ def query_url(query)
16
+ host = configuration[:host] || "www.datasciencetoolkit.org"
17
+ "#{protocol}://#{host}/maps/api/geocode/json?" + url_query_string(query)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,64 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/esri"
3
+ require 'geocoder/esri_token'
4
+
5
+ module Geocoder::Lookup
6
+ class Esri < Base
7
+
8
+ def name
9
+ "Esri"
10
+ end
11
+
12
+ def query_url(query)
13
+ search_keyword = query.reverse_geocode? ? "reverseGeocode" : "find"
14
+
15
+ "#{protocol}://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/#{search_keyword}?" +
16
+ url_query_string(query)
17
+ end
18
+
19
+ private # ---------------------------------------------------------------
20
+
21
+ def results(query)
22
+ return [] unless doc = fetch_data(query)
23
+
24
+ if (!query.reverse_geocode?)
25
+ return [] if !doc['locations'] || doc['locations'].empty?
26
+ end
27
+
28
+ if (doc['error'].nil?)
29
+ return [ doc ]
30
+ else
31
+ return []
32
+ end
33
+ end
34
+
35
+ def query_url_params(query)
36
+ params = {
37
+ :f => "pjson",
38
+ :outFields => "*"
39
+ }
40
+ if query.reverse_geocode?
41
+ params[:location] = query.coordinates.reverse.join(',')
42
+ else
43
+ params[:text] = query.sanitized_text
44
+ end
45
+ params[:token] = token
46
+ params[:forStorage] = configuration[:for_storage] if configuration[:for_storage]
47
+ params.merge(super)
48
+ end
49
+
50
+ def token
51
+ fetch_and_save_token! if !valid_token_configured? and configuration.api_key
52
+ configuration[:token].to_s unless configuration[:token].nil?
53
+ end
54
+
55
+ def valid_token_configured?
56
+ !configuration[:token].nil? and configuration[:token].active?
57
+ end
58
+
59
+ def fetch_and_save_token!
60
+ token_instance = Geocoder::EsriToken.generate_token(*configuration.api_key)
61
+ Geocoder.configure(:esri => Geocoder.config[:esri].merge({:token => token_instance}))
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,51 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/freegeoip'
3
+
4
+ module Geocoder::Lookup
5
+ class Freegeoip < Base
6
+
7
+ def name
8
+ "FreeGeoIP"
9
+ end
10
+
11
+ def supported_protocols
12
+ [:http]
13
+ end
14
+
15
+ def query_url(query)
16
+ "#{protocol}://#{host}/json/#{query.sanitized_text}"
17
+ end
18
+
19
+ private # ---------------------------------------------------------------
20
+
21
+ def parse_raw_data(raw_data)
22
+ raw_data.match(/^<html><title>404/) ? nil : super(raw_data)
23
+ end
24
+
25
+ def results(query)
26
+ # don't look up a loopback address, just return the stored result
27
+ return [reserved_result(query.text)] if query.loopback_ip_address?
28
+ # note: Freegeoip.net returns plain text "Not Found" on bad request
29
+ (doc = fetch_data(query)) ? [doc] : []
30
+ end
31
+
32
+ def reserved_result(ip)
33
+ {
34
+ "ip" => ip,
35
+ "city" => "",
36
+ "region_code" => "",
37
+ "region_name" => "",
38
+ "metrocode" => "",
39
+ "zipcode" => "",
40
+ "latitude" => "0",
41
+ "longitude" => "0",
42
+ "country_name" => "Reserved",
43
+ "country_code" => "RD"
44
+ }
45
+ end
46
+
47
+ def host
48
+ configuration[:host] || "freegeoip.io"
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,53 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/geocoder_ca"
3
+
4
+ module Geocoder::Lookup
5
+ class GeocoderCa < Base
6
+
7
+ def name
8
+ "Geocoder.ca"
9
+ end
10
+
11
+ def query_url(query)
12
+ "#{protocol}://geocoder.ca/?" + url_query_string(query)
13
+ end
14
+
15
+ private # ---------------------------------------------------------------
16
+
17
+ def results(query)
18
+ return [] unless doc = fetch_data(query)
19
+ if doc['error'].nil?
20
+ return [doc]
21
+ elsif doc['error']['code'] == "005"
22
+ # "Postal Code is not in the proper Format" => no results, just shut up
23
+ else
24
+ Geocoder.log(:warn, "Geocoder.ca service error: #{doc['error']['code']} (#{doc['error']['description']}).")
25
+ end
26
+ return []
27
+ end
28
+
29
+ def query_url_params(query)
30
+ params = {
31
+ :geoit => "xml",
32
+ :jsonp => 1,
33
+ :callback => "test",
34
+ :auth => configuration.api_key
35
+ }.merge(super)
36
+ if query.reverse_geocode?
37
+ lat,lon = query.coordinates
38
+ params[:latt] = lat
39
+ params[:longt] = lon
40
+ params[:corner] = 1
41
+ params[:reverse] = 1
42
+ else
43
+ params[:locate] = query.sanitized_text
44
+ params[:showpostal] = 1
45
+ end
46
+ params
47
+ end
48
+
49
+ def parse_raw_data(raw_data)
50
+ super raw_data[/^test\((.*)\)\;\s*$/, 1]
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/geocoder_us"
3
+
4
+ module Geocoder::Lookup
5
+ class GeocoderUs < Base
6
+
7
+ def name
8
+ "Geocoder.us"
9
+ end
10
+
11
+ def supported_protocols
12
+ [:http]
13
+ end
14
+
15
+ def query_url(query)
16
+ if configuration.api_key
17
+ "#{protocol}://#{configuration.api_key}@geocoder.us/member/service/csv/geocode?" + url_query_string(query)
18
+ else
19
+ "#{protocol}://geocoder.us/service/csv/geocode?" + url_query_string(query)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def results(query)
26
+ return [] unless doc = fetch_data(query)
27
+ if doc[0].to_s =~ /^(\d+)\:/
28
+ return []
29
+ else
30
+ return [doc.size == 5 ? ((doc[0..1] << nil) + doc[2..4]) : doc]
31
+ end
32
+ end
33
+
34
+ def query_url_params(query)
35
+ (query.text =~ /^\d{5}(?:-\d{4})?$/ ? {:zip => query} : {:address => query.sanitized_text}).merge(super)
36
+ end
37
+
38
+ def parse_raw_data(raw_data)
39
+ raw_data.chomp.split(',')
40
+ end
41
+ end
42
+ end
43
+
@@ -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 query_url(query)
12
+ path = query.reverse_geocode? ? "reverse" : "geocode"
13
+ "#{protocol}://api.geocod.io/v1/#{path}?#{url_query_string(query)}"
14
+ end
15
+
16
+ def results(query)
17
+ return [] unless doc = fetch_data(query)
18
+ return doc["results"] if doc['error'].nil?
19
+
20
+ if doc['error'] == 'Invalid API key'
21
+ raise_error(Geocoder::InvalidApiKey) ||
22
+ Geocoder.log(:warn, "Geocodio service error: invalid API key.")
23
+ elsif doc['error'].match(/You have reached your daily maximum/)
24
+ raise_error(Geocoder::OverQueryLimitError, doc['error']) ||
25
+ Geocoder.log(:warn, "Geocodio service error: #{doc['error']}.")
26
+ else
27
+ raise_error(Geocoder::InvalidRequest, doc['error']) ||
28
+ Geocoder.log(:warn, "Geocodio service error: #{doc['error']}.")
29
+ end
30
+ []
31
+ end
32
+
33
+ private # ---------------------------------------------------------------
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,45 @@
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
+ result = @mmdb.lookup(query.to_s)
41
+ result.nil? ? [] : [result]
42
+ end
43
+ end
44
+ end
45
+ 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
+ def query_url(query)
13
+ url_base_path(query) + url_query_string(query)
14
+ end
15
+
16
+ private
17
+
18
+ def url_base_path(query)
19
+ query.reverse_geocode? ? reverse_geocode_url_base_path : search_url_base_path
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
@@ -0,0 +1,91 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/google"
3
+
4
+ module Geocoder::Lookup
5
+ class Google < Base
6
+
7
+ def name
8
+ "Google"
9
+ end
10
+
11
+ def map_link_url(coordinates)
12
+ "http://maps.google.com/maps?q=#{coordinates.join(',')}"
13
+ end
14
+
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
22
+ end
23
+
24
+ def query_url(query)
25
+ "#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + url_query_string(query)
26
+ end
27
+
28
+ private # ---------------------------------------------------------------
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
+
41
+ def valid_response?(response)
42
+ json = parse_json(response.body)
43
+ status = json["status"] if json
44
+ super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
45
+ end
46
+
47
+ def results(query)
48
+ return [] unless doc = fetch_data(query)
49
+ case doc['status']; when "OK" # OK status implies >0 results
50
+ return doc['results']
51
+ when "OVER_QUERY_LIMIT"
52
+ raise_error(Geocoder::OverQueryLimitError) ||
53
+ Geocoder.log(:warn, "Google Geocoding API error: over query limit.")
54
+ when "REQUEST_DENIED"
55
+ raise_error(Geocoder::RequestDenied) ||
56
+ Geocoder.log(:warn, "Google Geocoding API error: request denied.")
57
+ when "INVALID_REQUEST"
58
+ raise_error(Geocoder::InvalidRequest) ||
59
+ Geocoder.log(:warn, "Google Geocoding API error: invalid request.")
60
+ end
61
+ return []
62
+ end
63
+
64
+ def query_url_google_params(query)
65
+ params = {
66
+ (query.reverse_geocode? ? :latlng : :address) => query.sanitized_text,
67
+ :sensor => "false",
68
+ :language => (query.language || configuration.language)
69
+ }
70
+ unless (bounds = query.options[:bounds]).nil?
71
+ params[:bounds] = bounds.map{ |point| "%f,%f" % point }.join('|')
72
+ end
73
+ unless (region = query.options[:region]).nil?
74
+ params[:region] = region
75
+ end
76
+ unless (components = query.options[:components]).nil?
77
+ params[:components] = components.is_a?(Array) ? components.join("|") : components
78
+ end
79
+ unless (result_type = query.options[:result_type]).nil?
80
+ params[:result_type] = result_type.is_a?(Array) ? result_type.join("|") : result_type
81
+ end
82
+ params
83
+ end
84
+
85
+ def query_url_params(query)
86
+ query_url_google_params(query).merge(
87
+ :key => configuration.api_key
88
+ ).merge(super)
89
+ end
90
+ end
91
+ end