really-broken-geocoder 1.5.1

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 (136) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +557 -0
  3. data/LICENSE +20 -0
  4. data/README.md +3 -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 +22 -0
  12. data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +30 -0
  13. data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +30 -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/generators/geocoder/migration_version.rb +15 -0
  17. data/lib/geocoder.rb +48 -0
  18. data/lib/geocoder/cache.rb +94 -0
  19. data/lib/geocoder/calculations.rb +420 -0
  20. data/lib/geocoder/cli.rb +121 -0
  21. data/lib/geocoder/configuration.rb +137 -0
  22. data/lib/geocoder/configuration_hash.rb +11 -0
  23. data/lib/geocoder/esri_token.rb +38 -0
  24. data/lib/geocoder/exceptions.rb +40 -0
  25. data/lib/geocoder/ip_address.rb +26 -0
  26. data/lib/geocoder/kernel_logger.rb +25 -0
  27. data/lib/geocoder/logger.rb +47 -0
  28. data/lib/geocoder/lookup.rb +118 -0
  29. data/lib/geocoder/lookups/amap.rb +63 -0
  30. data/lib/geocoder/lookups/baidu.rb +63 -0
  31. data/lib/geocoder/lookups/baidu_ip.rb +30 -0
  32. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +130 -0
  33. data/lib/geocoder/lookups/base.rb +348 -0
  34. data/lib/geocoder/lookups/bing.rb +82 -0
  35. data/lib/geocoder/lookups/db_ip_com.rb +52 -0
  36. data/lib/geocoder/lookups/dstk.rb +22 -0
  37. data/lib/geocoder/lookups/esri.rb +95 -0
  38. data/lib/geocoder/lookups/freegeoip.rb +60 -0
  39. data/lib/geocoder/lookups/geocoder_ca.rb +53 -0
  40. data/lib/geocoder/lookups/geocoder_us.rb +51 -0
  41. data/lib/geocoder/lookups/geocodio.rb +42 -0
  42. data/lib/geocoder/lookups/geoip2.rb +45 -0
  43. data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
  44. data/lib/geocoder/lookups/google.rb +95 -0
  45. data/lib/geocoder/lookups/google_places_details.rb +50 -0
  46. data/lib/geocoder/lookups/google_places_search.rb +33 -0
  47. data/lib/geocoder/lookups/google_premier.rb +57 -0
  48. data/lib/geocoder/lookups/here.rb +77 -0
  49. data/lib/geocoder/lookups/ip2location.rb +75 -0
  50. data/lib/geocoder/lookups/ipapi_com.rb +82 -0
  51. data/lib/geocoder/lookups/ipdata_co.rb +62 -0
  52. data/lib/geocoder/lookups/ipinfo_io.rb +44 -0
  53. data/lib/geocoder/lookups/ipstack.rb +63 -0
  54. data/lib/geocoder/lookups/latlon.rb +59 -0
  55. data/lib/geocoder/lookups/location_iq.rb +50 -0
  56. data/lib/geocoder/lookups/mapbox.rb +59 -0
  57. data/lib/geocoder/lookups/mapquest.rb +58 -0
  58. data/lib/geocoder/lookups/maxmind.rb +90 -0
  59. data/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
  60. data/lib/geocoder/lookups/maxmind_local.rb +65 -0
  61. data/lib/geocoder/lookups/nominatim.rb +64 -0
  62. data/lib/geocoder/lookups/opencagedata.rb +65 -0
  63. data/lib/geocoder/lookups/pelias.rb +63 -0
  64. data/lib/geocoder/lookups/pickpoint.rb +41 -0
  65. data/lib/geocoder/lookups/pointpin.rb +69 -0
  66. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +50 -0
  67. data/lib/geocoder/lookups/postcodes_io.rb +31 -0
  68. data/lib/geocoder/lookups/smarty_streets.rb +63 -0
  69. data/lib/geocoder/lookups/telize.rb +75 -0
  70. data/lib/geocoder/lookups/tencent.rb +59 -0
  71. data/lib/geocoder/lookups/test.rb +44 -0
  72. data/lib/geocoder/lookups/yandex.rb +62 -0
  73. data/lib/geocoder/models/active_record.rb +51 -0
  74. data/lib/geocoder/models/base.rb +39 -0
  75. data/lib/geocoder/models/mongo_base.rb +62 -0
  76. data/lib/geocoder/models/mongo_mapper.rb +26 -0
  77. data/lib/geocoder/models/mongoid.rb +32 -0
  78. data/lib/geocoder/query.rb +125 -0
  79. data/lib/geocoder/railtie.rb +26 -0
  80. data/lib/geocoder/request.rb +114 -0
  81. data/lib/geocoder/results/amap.rb +87 -0
  82. data/lib/geocoder/results/baidu.rb +79 -0
  83. data/lib/geocoder/results/baidu_ip.rb +62 -0
  84. data/lib/geocoder/results/ban_data_gouv_fr.rb +257 -0
  85. data/lib/geocoder/results/base.rb +79 -0
  86. data/lib/geocoder/results/bing.rb +52 -0
  87. data/lib/geocoder/results/db_ip_com.rb +58 -0
  88. data/lib/geocoder/results/dstk.rb +6 -0
  89. data/lib/geocoder/results/esri.rb +75 -0
  90. data/lib/geocoder/results/freegeoip.rb +40 -0
  91. data/lib/geocoder/results/geocoder_ca.rb +60 -0
  92. data/lib/geocoder/results/geocoder_us.rb +39 -0
  93. data/lib/geocoder/results/geocodio.rb +78 -0
  94. data/lib/geocoder/results/geoip2.rb +76 -0
  95. data/lib/geocoder/results/geoportail_lu.rb +71 -0
  96. data/lib/geocoder/results/google.rb +150 -0
  97. data/lib/geocoder/results/google_places_details.rb +39 -0
  98. data/lib/geocoder/results/google_places_search.rb +52 -0
  99. data/lib/geocoder/results/google_premier.rb +6 -0
  100. data/lib/geocoder/results/here.rb +79 -0
  101. data/lib/geocoder/results/ip2location.rb +22 -0
  102. data/lib/geocoder/results/ipapi_com.rb +45 -0
  103. data/lib/geocoder/results/ipdata_co.rb +40 -0
  104. data/lib/geocoder/results/ipinfo_io.rb +48 -0
  105. data/lib/geocoder/results/ipstack.rb +60 -0
  106. data/lib/geocoder/results/latlon.rb +71 -0
  107. data/lib/geocoder/results/location_iq.rb +6 -0
  108. data/lib/geocoder/results/mapbox.rb +57 -0
  109. data/lib/geocoder/results/mapquest.rb +48 -0
  110. data/lib/geocoder/results/maxmind.rb +130 -0
  111. data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
  112. data/lib/geocoder/results/maxmind_local.rb +44 -0
  113. data/lib/geocoder/results/nominatim.rb +109 -0
  114. data/lib/geocoder/results/opencagedata.rb +100 -0
  115. data/lib/geocoder/results/pelias.rb +58 -0
  116. data/lib/geocoder/results/pickpoint.rb +6 -0
  117. data/lib/geocoder/results/pointpin.rb +40 -0
  118. data/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
  119. data/lib/geocoder/results/postcodes_io.rb +40 -0
  120. data/lib/geocoder/results/smarty_streets.rb +142 -0
  121. data/lib/geocoder/results/telize.rb +40 -0
  122. data/lib/geocoder/results/tencent.rb +72 -0
  123. data/lib/geocoder/results/test.rb +33 -0
  124. data/lib/geocoder/results/yandex.rb +134 -0
  125. data/lib/geocoder/sql.rb +110 -0
  126. data/lib/geocoder/stores/active_record.rb +328 -0
  127. data/lib/geocoder/stores/base.rb +115 -0
  128. data/lib/geocoder/stores/mongo_base.rb +58 -0
  129. data/lib/geocoder/stores/mongo_mapper.rb +13 -0
  130. data/lib/geocoder/stores/mongoid.rb +13 -0
  131. data/lib/geocoder/version.rb +3 -0
  132. data/lib/hash_recursive_merge.rb +74 -0
  133. data/lib/maxmind_database.rb +109 -0
  134. data/lib/tasks/geocoder.rake +54 -0
  135. data/lib/tasks/maxmind.rake +73 -0
  136. metadata +186 -0
@@ -0,0 +1,137 @@
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
+ ##
42
+ # Merge the given hash into a lookup's existing configuration.
43
+ #
44
+ def self.merge_into_lookup_config(lookup_name, options)
45
+ base = Geocoder.config[lookup_name]
46
+ Geocoder.configure(lookup_name => base.merge(options))
47
+ end
48
+
49
+ class Configuration
50
+ include Singleton
51
+
52
+ OPTIONS = [
53
+ :timeout,
54
+ :lookup,
55
+ :ip_lookup,
56
+ :language,
57
+ :http_headers,
58
+ :use_https,
59
+ :http_proxy,
60
+ :https_proxy,
61
+ :api_key,
62
+ :cache,
63
+ :cache_prefix,
64
+ :always_raise,
65
+ :units,
66
+ :distances,
67
+ :basic_auth,
68
+ :logger,
69
+ :kernel_logger_level
70
+ ]
71
+
72
+ attr_accessor :data
73
+
74
+ def self.set_defaults
75
+ instance.set_defaults
76
+ end
77
+
78
+ OPTIONS.each do |o|
79
+ define_method o do
80
+ @data[o]
81
+ end
82
+ define_method "#{o}=" do |value|
83
+ @data[o] = value
84
+ end
85
+ end
86
+
87
+ def configure(options)
88
+ @data.rmerge!(options)
89
+ end
90
+
91
+ def initialize # :nodoc
92
+ @data = Geocoder::ConfigurationHash.new
93
+ set_defaults
94
+ end
95
+
96
+ def set_defaults
97
+
98
+ # geocoding options
99
+ @data[:timeout] = 3 # geocoding service timeout (secs)
100
+ @data[:lookup] = :nominatim # name of street address geocoding service (symbol)
101
+ @data[:ip_lookup] = :ipinfo_io # name of IP address geocoding service (symbol)
102
+ @data[:language] = :en # ISO-639 language code
103
+ @data[:http_headers] = {} # HTTP headers for lookup
104
+ @data[:use_https] = false # use HTTPS for lookup requests? (if supported)
105
+ @data[:http_proxy] = nil # HTTP proxy server (user:pass@host:port)
106
+ @data[:https_proxy] = nil # HTTPS proxy server (user:pass@host:port)
107
+ @data[:api_key] = nil # API key for geocoding service
108
+ @data[:cache] = nil # cache object (must respond to #[], #[]=, and #keys)
109
+ @data[:cache_prefix] = "geocoder:" # prefix (string) to use for all cache keys
110
+ @data[:basic_auth] = {} # user and password for basic auth ({:user => "user", :password => "password"})
111
+ @data[:logger] = :kernel # :kernel or Logger instance
112
+ @data[:kernel_logger_level] = ::Logger::WARN # log level, if kernel logger is used
113
+
114
+ # exceptions that should not be rescued by default
115
+ # (if you want to implement custom error handling);
116
+ # supports SocketError and Timeout::Error
117
+ @data[:always_raise] = []
118
+
119
+ # calculation options
120
+ @data[:units] = :mi # :mi or :km
121
+ @data[:distances] = :linear # :linear or :spherical
122
+ end
123
+
124
+ instance_eval(OPTIONS.map do |option|
125
+ o = option.to_s
126
+ <<-EOS
127
+ def #{o}
128
+ instance.data[:#{o}]
129
+ end
130
+
131
+ def #{o}=(value)
132
+ instance.data[:#{o}] = value
133
+ end
134
+ EOS
135
+ end.join("\n\n"))
136
+ end
137
+ end
@@ -0,0 +1,11 @@
1
+ require 'hash_recursive_merge'
2
+
3
+ module Geocoder
4
+ class ConfigurationHash < Hash
5
+ include HashRecursiveMerge
6
+
7
+ def method_missing(meth, *args, &block)
8
+ has_key?(meth) ? self[meth] : super
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,38 @@
1
+ module Geocoder
2
+ class EsriToken
3
+ attr_accessor :value, :expires_at
4
+
5
+ def initialize(value, expires_at)
6
+ @value = value
7
+ @expires_at = expires_at
8
+ end
9
+
10
+ def to_s
11
+ @value
12
+ end
13
+
14
+ def active?
15
+ @expires_at > Time.now
16
+ end
17
+
18
+ def self.generate_token(client_id, client_secret, expires=1440)
19
+ # creates a new token that will expire in 1 day by default
20
+ getToken = Net::HTTP.post_form URI('https://www.arcgis.com/sharing/rest/oauth2/token'),
21
+ f: 'json',
22
+ client_id: client_id,
23
+ client_secret: client_secret,
24
+ grant_type: 'client_credentials',
25
+ expiration: expires # (minutes) max: 20160, default: 1 day
26
+
27
+ response = JSON.parse(getToken.body)
28
+
29
+ if response['error']
30
+ Geocoder.log(:warn, response['error'])
31
+ else
32
+ token_value = response['access_token']
33
+ expires_at = Time.now + (expires * 60)
34
+ new(token_value, expires_at)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ require 'timeout'
2
+
3
+ module Geocoder
4
+
5
+ class Error < StandardError
6
+ end
7
+
8
+ class ConfigurationError < Error
9
+ end
10
+
11
+ class OverQueryLimitError < Error
12
+ end
13
+
14
+ class ResponseParseError < Error
15
+ attr_reader :response
16
+
17
+ def initialize(response)
18
+ @response = response
19
+ end
20
+ end
21
+
22
+ class RequestDenied < Error
23
+ end
24
+
25
+ class InvalidRequest < Error
26
+ end
27
+
28
+ class InvalidApiKey < Error
29
+ end
30
+
31
+ class ServiceUnavailable < Error
32
+ end
33
+
34
+ class LookupTimeout < ::Timeout::Error
35
+ end
36
+
37
+ class NetworkError < Error
38
+ end
39
+
40
+ end
@@ -0,0 +1,26 @@
1
+ require 'resolv'
2
+ module Geocoder
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
13
+
14
+ def loopback?
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) }
20
+ end
21
+
22
+ def valid?
23
+ !!((self =~ Resolv::IPv4::Regex) || (self =~ Resolv::IPv6::Regex))
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Geocoder
2
+ class KernelLogger
3
+ include Singleton
4
+
5
+ def add(level, message)
6
+ return unless log_message_at_level?(level)
7
+ case level
8
+ when ::Logger::DEBUG, ::Logger::INFO
9
+ puts message
10
+ when ::Logger::WARN
11
+ warn message
12
+ when ::Logger::ERROR
13
+ raise message
14
+ when ::Logger::FATAL
15
+ fail message
16
+ end
17
+ end
18
+
19
+ private # ----------------------------------------------------------------
20
+
21
+ def log_message_at_level?(level)
22
+ level >= Geocoder.config.kernel_logger_level
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,47 @@
1
+ require 'logger'
2
+
3
+ module Geocoder
4
+
5
+ def self.log(level, message)
6
+ Logger.instance.log(level, message)
7
+ end
8
+
9
+ class Logger
10
+ include Singleton
11
+
12
+ SEVERITY = {
13
+ debug: ::Logger::DEBUG,
14
+ info: ::Logger::INFO,
15
+ warn: ::Logger::WARN,
16
+ error: ::Logger::ERROR,
17
+ fatal: ::Logger::FATAL
18
+ }
19
+
20
+ def log(level, message)
21
+ unless valid_level?(level)
22
+ raise StandardError, "Geocoder tried to log a message with an invalid log level."
23
+ end
24
+ if current_logger.respond_to? :add
25
+ current_logger.add(SEVERITY[level], message)
26
+ else
27
+ raise Geocoder::ConfigurationError, "Please specify valid logger for Geocoder. " +
28
+ "Logger specified must be :kernel or must respond to `add(level, message)`."
29
+ end
30
+ nil
31
+ end
32
+
33
+ private # ----------------------------------------------------------------
34
+
35
+ def current_logger
36
+ logger = Geocoder.config[:logger]
37
+ if logger == :kernel
38
+ logger = Geocoder::KernelLogger.instance
39
+ end
40
+ logger
41
+ end
42
+
43
+ def valid_level?(level)
44
+ SEVERITY.keys.include?(level)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,118 @@
1
+ require "geocoder/lookups/test"
2
+
3
+ module Geocoder
4
+ module Lookup
5
+ extend self
6
+
7
+ ##
8
+ # Array of valid Lookup service names.
9
+ #
10
+ def all_services
11
+ street_services + ip_services
12
+ end
13
+
14
+ ##
15
+ # Array of valid Lookup service names, excluding :test.
16
+ #
17
+ def all_services_except_test
18
+ all_services - [:test]
19
+ end
20
+
21
+ ##
22
+ # All street address lookup services, default first.
23
+ #
24
+ def street_services
25
+ @street_services ||= [
26
+ :location_iq,
27
+ :dstk,
28
+ :esri,
29
+ :google,
30
+ :google_premier,
31
+ :google_places_details,
32
+ :google_places_search,
33
+ :bing,
34
+ :geocoder_ca,
35
+ :geocoder_us,
36
+ :yandex,
37
+ :nominatim,
38
+ :mapbox,
39
+ :mapquest,
40
+ :opencagedata,
41
+ :pelias,
42
+ :pickpoint,
43
+ :here,
44
+ :baidu,
45
+ :tencent,
46
+ :geocodio,
47
+ :smarty_streets,
48
+ :postcode_anywhere_uk,
49
+ :postcodes_io,
50
+ :geoportail_lu,
51
+ :ban_data_gouv_fr,
52
+ :test,
53
+ :latlon,
54
+ :amap
55
+ ]
56
+ end
57
+
58
+ ##
59
+ # All IP address lookup services, default first.
60
+ #
61
+ def ip_services
62
+ @ip_services ||= [
63
+ :baidu_ip,
64
+ :freegeoip,
65
+ :geoip2,
66
+ :maxmind,
67
+ :maxmind_local,
68
+ :telize,
69
+ :pointpin,
70
+ :maxmind_geoip2,
71
+ :ipinfo_io,
72
+ :ipapi_com,
73
+ :ipdata_co,
74
+ :db_ip_com,
75
+ :ipstack,
76
+ :ip2location
77
+ ]
78
+ end
79
+
80
+ attr_writer :street_services, :ip_services
81
+
82
+ ##
83
+ # Retrieve a Lookup object from the store.
84
+ # Use this instead of Geocoder::Lookup::X.new to get an
85
+ # already-configured Lookup object.
86
+ #
87
+ def get(name)
88
+ @services = {} unless defined?(@services)
89
+ @services[name] = spawn(name) unless @services.include?(name)
90
+ @services[name]
91
+ end
92
+
93
+
94
+ private # -----------------------------------------------------------------
95
+
96
+ ##
97
+ # Spawn a Lookup of the given name.
98
+ #
99
+ def spawn(name)
100
+ if all_services.include?(name)
101
+ name = name.to_s
102
+ require "geocoder/lookups/#{name}"
103
+ Geocoder::Lookup.const_get(classify_name(name)).new
104
+ else
105
+ valids = all_services.map(&:inspect).join(", ")
106
+ raise ConfigurationError, "Please specify a valid lookup for Geocoder " +
107
+ "(#{name.inspect} is not one of: #{valids})."
108
+ end
109
+ end
110
+
111
+ ##
112
+ # Convert an "underscore" version of a name into a "class" version.
113
+ #
114
+ def classify_name(filename)
115
+ filename.to_s.split("_").map{ |i| i[0...1].upcase + i[1..-1] }.join
116
+ end
117
+ end
118
+ end