ultra-fast-mod 0.0.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 (175) hide show
  1. checksums.yaml +7 -0
  2. data/geocoder-1.8.6/CHANGELOG.md +669 -0
  3. data/geocoder-1.8.6/LICENSE +20 -0
  4. data/geocoder-1.8.6/README.md +827 -0
  5. data/geocoder-1.8.6/bin/console +13 -0
  6. data/geocoder-1.8.6/bin/geocode +5 -0
  7. data/geocoder-1.8.6/examples/app_defined_lookup_services.rb +22 -0
  8. data/geocoder-1.8.6/examples/cache_bypass.rb +48 -0
  9. data/geocoder-1.8.6/examples/reverse_geocode_job.rb +40 -0
  10. data/geocoder-1.8.6/lib/easting_northing.rb +171 -0
  11. data/geocoder-1.8.6/lib/generators/geocoder/config/config_generator.rb +14 -0
  12. data/geocoder-1.8.6/lib/generators/geocoder/config/templates/initializer.rb +27 -0
  13. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/geolite_city_generator.rb +30 -0
  14. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/geolite_country_generator.rb +30 -0
  15. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
  16. data/geocoder-1.8.6/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
  17. data/geocoder-1.8.6/lib/generators/geocoder/migration_version.rb +15 -0
  18. data/geocoder-1.8.6/lib/geocoder/cache.rb +77 -0
  19. data/geocoder-1.8.6/lib/geocoder/cache_stores/base.rb +40 -0
  20. data/geocoder-1.8.6/lib/geocoder/cache_stores/generic.rb +35 -0
  21. data/geocoder-1.8.6/lib/geocoder/cache_stores/redis.rb +34 -0
  22. data/geocoder-1.8.6/lib/geocoder/calculations.rb +420 -0
  23. data/geocoder-1.8.6/lib/geocoder/cli.rb +121 -0
  24. data/geocoder-1.8.6/lib/geocoder/configuration.rb +151 -0
  25. data/geocoder-1.8.6/lib/geocoder/configuration_hash.rb +11 -0
  26. data/geocoder-1.8.6/lib/geocoder/esri_token.rb +38 -0
  27. data/geocoder-1.8.6/lib/geocoder/exceptions.rb +40 -0
  28. data/geocoder-1.8.6/lib/geocoder/ip_address.rb +36 -0
  29. data/geocoder-1.8.6/lib/geocoder/kernel_logger.rb +25 -0
  30. data/geocoder-1.8.6/lib/geocoder/logger.rb +47 -0
  31. data/geocoder-1.8.6/lib/geocoder/lookup.rb +155 -0
  32. data/geocoder-1.8.6/lib/geocoder/lookups/abstract_api.rb +46 -0
  33. data/geocoder-1.8.6/lib/geocoder/lookups/amap.rb +63 -0
  34. data/geocoder-1.8.6/lib/geocoder/lookups/amazon_location_service.rb +58 -0
  35. data/geocoder-1.8.6/lib/geocoder/lookups/azure.rb +56 -0
  36. data/geocoder-1.8.6/lib/geocoder/lookups/baidu.rb +63 -0
  37. data/geocoder-1.8.6/lib/geocoder/lookups/baidu_ip.rb +30 -0
  38. data/geocoder-1.8.6/lib/geocoder/lookups/ban_data_gouv_fr.rb +143 -0
  39. data/geocoder-1.8.6/lib/geocoder/lookups/base.rb +351 -0
  40. data/geocoder-1.8.6/lib/geocoder/lookups/bing.rb +82 -0
  41. data/geocoder-1.8.6/lib/geocoder/lookups/db_ip_com.rb +52 -0
  42. data/geocoder-1.8.6/lib/geocoder/lookups/esri.rb +114 -0
  43. data/geocoder-1.8.6/lib/geocoder/lookups/freegeoip.rb +62 -0
  44. data/geocoder-1.8.6/lib/geocoder/lookups/geoapify.rb +78 -0
  45. data/geocoder-1.8.6/lib/geocoder/lookups/geocoder_ca.rb +53 -0
  46. data/geocoder-1.8.6/lib/geocoder/lookups/geocodio.rb +42 -0
  47. data/geocoder-1.8.6/lib/geocoder/lookups/geoip2.rb +49 -0
  48. data/geocoder-1.8.6/lib/geocoder/lookups/geoportail_lu.rb +65 -0
  49. data/geocoder-1.8.6/lib/geocoder/lookups/google.rb +100 -0
  50. data/geocoder-1.8.6/lib/geocoder/lookups/google_places_details.rb +64 -0
  51. data/geocoder-1.8.6/lib/geocoder/lookups/google_places_search.rb +75 -0
  52. data/geocoder-1.8.6/lib/geocoder/lookups/google_premier.rb +61 -0
  53. data/geocoder-1.8.6/lib/geocoder/lookups/here.rb +73 -0
  54. data/geocoder-1.8.6/lib/geocoder/lookups/ip2location.rb +71 -0
  55. data/geocoder-1.8.6/lib/geocoder/lookups/ip2location_io.rb +62 -0
  56. data/geocoder-1.8.6/lib/geocoder/lookups/ip2location_lite.rb +40 -0
  57. data/geocoder-1.8.6/lib/geocoder/lookups/ipapi_com.rb +82 -0
  58. data/geocoder-1.8.6/lib/geocoder/lookups/ipbase.rb +49 -0
  59. data/geocoder-1.8.6/lib/geocoder/lookups/ipdata_co.rb +62 -0
  60. data/geocoder-1.8.6/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  61. data/geocoder-1.8.6/lib/geocoder/lookups/ipinfo_io.rb +44 -0
  62. data/geocoder-1.8.6/lib/geocoder/lookups/ipinfo_io_lite.rb +42 -0
  63. data/geocoder-1.8.6/lib/geocoder/lookups/ipqualityscore.rb +50 -0
  64. data/geocoder-1.8.6/lib/geocoder/lookups/ipregistry.rb +68 -0
  65. data/geocoder-1.8.6/lib/geocoder/lookups/ipstack.rb +63 -0
  66. data/geocoder-1.8.6/lib/geocoder/lookups/latlon.rb +58 -0
  67. data/geocoder-1.8.6/lib/geocoder/lookups/location_iq.rb +54 -0
  68. data/geocoder-1.8.6/lib/geocoder/lookups/mapbox.rb +60 -0
  69. data/geocoder-1.8.6/lib/geocoder/lookups/mapquest.rb +58 -0
  70. data/geocoder-1.8.6/lib/geocoder/lookups/maxmind.rb +90 -0
  71. data/geocoder-1.8.6/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
  72. data/geocoder-1.8.6/lib/geocoder/lookups/maxmind_local.rb +71 -0
  73. data/geocoder-1.8.6/lib/geocoder/lookups/melissa_street.rb +41 -0
  74. data/geocoder-1.8.6/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
  75. data/geocoder-1.8.6/lib/geocoder/lookups/nominatim.rb +64 -0
  76. data/geocoder-1.8.6/lib/geocoder/lookups/opencagedata.rb +65 -0
  77. data/geocoder-1.8.6/lib/geocoder/lookups/osmnames.rb +57 -0
  78. data/geocoder-1.8.6/lib/geocoder/lookups/pc_miler.rb +87 -0
  79. data/geocoder-1.8.6/lib/geocoder/lookups/pdok_nl.rb +43 -0
  80. data/geocoder-1.8.6/lib/geocoder/lookups/pelias.rb +63 -0
  81. data/geocoder-1.8.6/lib/geocoder/lookups/photon.rb +89 -0
  82. data/geocoder-1.8.6/lib/geocoder/lookups/pickpoint.rb +41 -0
  83. data/geocoder-1.8.6/lib/geocoder/lookups/pointpin.rb +69 -0
  84. data/geocoder-1.8.6/lib/geocoder/lookups/postcode_anywhere_uk.rb +50 -0
  85. data/geocoder-1.8.6/lib/geocoder/lookups/postcodes_io.rb +31 -0
  86. data/geocoder-1.8.6/lib/geocoder/lookups/smarty_streets.rb +68 -0
  87. data/geocoder-1.8.6/lib/geocoder/lookups/telize.rb +75 -0
  88. data/geocoder-1.8.6/lib/geocoder/lookups/tencent.rb +59 -0
  89. data/geocoder-1.8.6/lib/geocoder/lookups/test.rb +49 -0
  90. data/geocoder-1.8.6/lib/geocoder/lookups/twogis.rb +58 -0
  91. data/geocoder-1.8.6/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
  92. data/geocoder-1.8.6/lib/geocoder/lookups/yandex.rb +61 -0
  93. data/geocoder-1.8.6/lib/geocoder/models/active_record.rb +51 -0
  94. data/geocoder-1.8.6/lib/geocoder/models/base.rb +39 -0
  95. data/geocoder-1.8.6/lib/geocoder/models/mongo_base.rb +62 -0
  96. data/geocoder-1.8.6/lib/geocoder/models/mongo_mapper.rb +26 -0
  97. data/geocoder-1.8.6/lib/geocoder/models/mongoid.rb +32 -0
  98. data/geocoder-1.8.6/lib/geocoder/query.rb +125 -0
  99. data/geocoder-1.8.6/lib/geocoder/railtie.rb +26 -0
  100. data/geocoder-1.8.6/lib/geocoder/request.rb +114 -0
  101. data/geocoder-1.8.6/lib/geocoder/results/abstract_api.rb +146 -0
  102. data/geocoder-1.8.6/lib/geocoder/results/amap.rb +87 -0
  103. data/geocoder-1.8.6/lib/geocoder/results/amazon_location_service.rb +62 -0
  104. data/geocoder-1.8.6/lib/geocoder/results/azure.rb +65 -0
  105. data/geocoder-1.8.6/lib/geocoder/results/baidu.rb +75 -0
  106. data/geocoder-1.8.6/lib/geocoder/results/baidu_ip.rb +62 -0
  107. data/geocoder-1.8.6/lib/geocoder/results/ban_data_gouv_fr.rb +282 -0
  108. data/geocoder-1.8.6/lib/geocoder/results/base.rb +79 -0
  109. data/geocoder-1.8.6/lib/geocoder/results/bing.rb +52 -0
  110. data/geocoder-1.8.6/lib/geocoder/results/db_ip_com.rb +58 -0
  111. data/geocoder-1.8.6/lib/geocoder/results/esri.rb +78 -0
  112. data/geocoder-1.8.6/lib/geocoder/results/freegeoip.rb +40 -0
  113. data/geocoder-1.8.6/lib/geocoder/results/geoapify.rb +179 -0
  114. data/geocoder-1.8.6/lib/geocoder/results/geocoder_ca.rb +60 -0
  115. data/geocoder-1.8.6/lib/geocoder/results/geocodio.rb +78 -0
  116. data/geocoder-1.8.6/lib/geocoder/results/geoip2.rb +76 -0
  117. data/geocoder-1.8.6/lib/geocoder/results/geoportail_lu.rb +71 -0
  118. data/geocoder-1.8.6/lib/geocoder/results/google.rb +150 -0
  119. data/geocoder-1.8.6/lib/geocoder/results/google_places_details.rb +39 -0
  120. data/geocoder-1.8.6/lib/geocoder/results/google_places_search.rb +52 -0
  121. data/geocoder-1.8.6/lib/geocoder/results/google_premier.rb +6 -0
  122. data/geocoder-1.8.6/lib/geocoder/results/here.rb +77 -0
  123. data/geocoder-1.8.6/lib/geocoder/results/ip2location.rb +22 -0
  124. data/geocoder-1.8.6/lib/geocoder/results/ip2location_io.rb +21 -0
  125. data/geocoder-1.8.6/lib/geocoder/results/ip2location_lite.rb +47 -0
  126. data/geocoder-1.8.6/lib/geocoder/results/ipapi_com.rb +45 -0
  127. data/geocoder-1.8.6/lib/geocoder/results/ipbase.rb +40 -0
  128. data/geocoder-1.8.6/lib/geocoder/results/ipdata_co.rb +40 -0
  129. data/geocoder-1.8.6/lib/geocoder/results/ipgeolocation.rb +59 -0
  130. data/geocoder-1.8.6/lib/geocoder/results/ipinfo_io.rb +48 -0
  131. data/geocoder-1.8.6/lib/geocoder/results/ipinfo_io_lite.rb +16 -0
  132. data/geocoder-1.8.6/lib/geocoder/results/ipqualityscore.rb +54 -0
  133. data/geocoder-1.8.6/lib/geocoder/results/ipregistry.rb +304 -0
  134. data/geocoder-1.8.6/lib/geocoder/results/ipstack.rb +60 -0
  135. data/geocoder-1.8.6/lib/geocoder/results/latlon.rb +71 -0
  136. data/geocoder-1.8.6/lib/geocoder/results/location_iq.rb +6 -0
  137. data/geocoder-1.8.6/lib/geocoder/results/mapbox.rb +80 -0
  138. data/geocoder-1.8.6/lib/geocoder/results/mapquest.rb +48 -0
  139. data/geocoder-1.8.6/lib/geocoder/results/maxmind.rb +130 -0
  140. data/geocoder-1.8.6/lib/geocoder/results/maxmind_geoip2.rb +9 -0
  141. data/geocoder-1.8.6/lib/geocoder/results/maxmind_local.rb +44 -0
  142. data/geocoder-1.8.6/lib/geocoder/results/melissa_street.rb +46 -0
  143. data/geocoder-1.8.6/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
  144. data/geocoder-1.8.6/lib/geocoder/results/nominatim.rb +121 -0
  145. data/geocoder-1.8.6/lib/geocoder/results/opencagedata.rb +100 -0
  146. data/geocoder-1.8.6/lib/geocoder/results/osmnames.rb +56 -0
  147. data/geocoder-1.8.6/lib/geocoder/results/pc_miler.rb +98 -0
  148. data/geocoder-1.8.6/lib/geocoder/results/pdok_nl.rb +62 -0
  149. data/geocoder-1.8.6/lib/geocoder/results/pelias.rb +58 -0
  150. data/geocoder-1.8.6/lib/geocoder/results/photon.rb +119 -0
  151. data/geocoder-1.8.6/lib/geocoder/results/pickpoint.rb +6 -0
  152. data/geocoder-1.8.6/lib/geocoder/results/pointpin.rb +40 -0
  153. data/geocoder-1.8.6/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
  154. data/geocoder-1.8.6/lib/geocoder/results/postcodes_io.rb +40 -0
  155. data/geocoder-1.8.6/lib/geocoder/results/smarty_streets.rb +142 -0
  156. data/geocoder-1.8.6/lib/geocoder/results/telize.rb +40 -0
  157. data/geocoder-1.8.6/lib/geocoder/results/tencent.rb +72 -0
  158. data/geocoder-1.8.6/lib/geocoder/results/test.rb +33 -0
  159. data/geocoder-1.8.6/lib/geocoder/results/twogis.rb +76 -0
  160. data/geocoder-1.8.6/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
  161. data/geocoder-1.8.6/lib/geocoder/results/yandex.rb +292 -0
  162. data/geocoder-1.8.6/lib/geocoder/sql.rb +110 -0
  163. data/geocoder-1.8.6/lib/geocoder/stores/active_record.rb +329 -0
  164. data/geocoder-1.8.6/lib/geocoder/stores/base.rb +115 -0
  165. data/geocoder-1.8.6/lib/geocoder/stores/mongo_base.rb +58 -0
  166. data/geocoder-1.8.6/lib/geocoder/stores/mongo_mapper.rb +13 -0
  167. data/geocoder-1.8.6/lib/geocoder/stores/mongoid.rb +13 -0
  168. data/geocoder-1.8.6/lib/geocoder/util.rb +29 -0
  169. data/geocoder-1.8.6/lib/geocoder/version.rb +3 -0
  170. data/geocoder-1.8.6/lib/geocoder.rb +48 -0
  171. data/geocoder-1.8.6/lib/maxmind_database.rb +109 -0
  172. data/geocoder-1.8.6/lib/tasks/geocoder.rake +54 -0
  173. data/geocoder-1.8.6/lib/tasks/maxmind.rake +73 -0
  174. data/ultra-fast-mod.gemspec +12 -0
  175. metadata +214 -0
@@ -0,0 +1,143 @@
1
+ # encoding: utf-8
2
+
3
+ require 'geocoder/lookups/base'
4
+ require 'geocoder/results/ban_data_gouv_fr'
5
+
6
+ module Geocoder::Lookup
7
+ class BanDataGouvFr < Base
8
+
9
+ def name
10
+ "Base Adresse Nationale Française"
11
+ end
12
+
13
+ def map_link_url(coordinates)
14
+ "https://www.openstreetmap.org/#map=19/#{coordinates.join('/')}"
15
+ end
16
+
17
+ private # ---------------------------------------------------------------
18
+
19
+ def base_query_url(query)
20
+ method = query.reverse_geocode? ? "reverse" : "search"
21
+ "#{protocol}://data.geopf.fr/geocodage/#{method}/?"
22
+ end
23
+
24
+ def any_result?(doc)
25
+ doc['features'] and doc['features'].any?
26
+ end
27
+
28
+ def results(query)
29
+ if doc = fetch_data(query) and any_result?(doc)
30
+ [doc]
31
+ else
32
+ []
33
+ end
34
+ end
35
+
36
+ #### PARAMS ####
37
+
38
+ def query_url_params(query)
39
+ query_ban_datagouv_fr_params(query).merge(super)
40
+ end
41
+
42
+ def query_ban_datagouv_fr_params(query)
43
+ query.reverse_geocode? ? reverse_geocode_ban_fr_params(query) : search_geocode_ban_fr_params(query)
44
+ end
45
+
46
+ #### SEARCH GEOCODING PARAMS ####
47
+ #
48
+ # :q => required, full text search param)
49
+
50
+ # :limit => force limit number of results returned by raw API
51
+ # (default = 5) note : only first result is taken
52
+ # in account in geocoder
53
+ #
54
+ # :autocomplete => pass 0 to disable autocomplete treatment of :q
55
+ # (default = 1)
56
+ #
57
+ # :lat => force filter results around specific lat/lon
58
+ #
59
+ # :lon => force filter results around specific lat/lon
60
+ #
61
+ # :type => force filter the returned result type
62
+ # (check results for a list of accepted types)
63
+ #
64
+ # :postcode => force filter results on a specific city post code
65
+ #
66
+ # :citycode => force filter results on a specific city UUID INSEE code
67
+ #
68
+ # For up to date doc (in french only) : https://adresse.data.gouv.fr/api/
69
+ #
70
+ def search_geocode_ban_fr_params(query)
71
+ params = {
72
+ q: query.sanitized_text
73
+ }
74
+ unless (limit = query.options[:limit]).nil? || !limit_param_is_valid?(limit)
75
+ params[:limit] = limit.to_i
76
+ end
77
+ unless (autocomplete = query.options[:autocomplete]).nil? || !autocomplete_param_is_valid?(autocomplete)
78
+ params[:autocomplete] = autocomplete.to_s
79
+ end
80
+ unless (type = query.options[:type]).nil? || !type_param_is_valid?(type)
81
+ params[:type] = type.downcase
82
+ end
83
+ unless (postcode = query.options[:postcode]).nil? || !code_param_is_valid?(postcode)
84
+ params[:postcode] = postcode.to_s
85
+ end
86
+ unless (citycode = query.options[:citycode]).nil? || !code_param_is_valid?(citycode)
87
+ params[:citycode] = citycode.to_s
88
+ end
89
+ unless (lat = query.options[:lat]).nil? || !latitude_is_valid?(lat)
90
+ params[:lat] = lat
91
+ end
92
+ unless (lon = query.options[:lon]).nil? || !longitude_is_valid?(lon)
93
+ params[:lon] = lon
94
+ end
95
+ params
96
+ end
97
+
98
+ #### REVERSE GEOCODING PARAMS ####
99
+ #
100
+ # :lat => required
101
+ #
102
+ # :lon => required
103
+ #
104
+ # :type => force returned results type
105
+ # (check results for a list of accepted types)
106
+ #
107
+ def reverse_geocode_ban_fr_params(query)
108
+ lat_lon = query.coordinates
109
+ params = {
110
+ lat: lat_lon.first,
111
+ lon: lat_lon.last
112
+ }
113
+ unless (type = query.options[:type]).nil? || !type_param_is_valid?(type)
114
+ params[:type] = type.downcase
115
+ end
116
+ params
117
+ end
118
+
119
+ def limit_param_is_valid?(param)
120
+ param.to_i.positive?
121
+ end
122
+
123
+ def autocomplete_param_is_valid?(param)
124
+ [0,1].include?(param.to_i)
125
+ end
126
+
127
+ def type_param_is_valid?(param)
128
+ %w(housenumber street locality municipality).include?(param.downcase)
129
+ end
130
+
131
+ def code_param_is_valid?(param)
132
+ (1..99999).include?(param.to_i)
133
+ end
134
+
135
+ def latitude_is_valid?(param)
136
+ param.to_f <= 90 && param.to_f >= -90
137
+ end
138
+
139
+ def longitude_is_valid?(param)
140
+ param.to_f <= 180 && param.to_f >= -180
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,351 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'uri'
4
+
5
+ unless defined?(ActiveSupport::JSON)
6
+ begin
7
+ require 'json'
8
+ rescue LoadError
9
+ raise LoadError, "Please install the 'json' or 'json_pure' gem to parse geocoder results."
10
+ end
11
+ end
12
+
13
+ module Geocoder
14
+ module Lookup
15
+
16
+ class Base
17
+ def initialize
18
+ @cache = nil
19
+ end
20
+
21
+ ##
22
+ # Human-readable name of the geocoding API.
23
+ #
24
+ def name
25
+ fail
26
+ end
27
+
28
+ ##
29
+ # Symbol which is used in configuration to refer to this Lookup.
30
+ #
31
+ def handle
32
+ str = self.class.to_s
33
+ str[str.rindex(':')+1..-1].gsub(/([a-z\d]+)([A-Z])/,'\1_\2').downcase.to_sym
34
+ end
35
+
36
+ ##
37
+ # Query the geocoding API and return a Geocoder::Result object.
38
+ # Returns +nil+ on timeout or error.
39
+ #
40
+ # Takes a search string (eg: "Mississippi Coast Coliseumf, Biloxi, MS",
41
+ # "205.128.54.202") for geocoding, or coordinates (latitude, longitude)
42
+ # for reverse geocoding. Returns an array of <tt>Geocoder::Result</tt>s.
43
+ #
44
+ def search(query, options = {})
45
+ query = Geocoder::Query.new(query, options) unless query.is_a?(Geocoder::Query)
46
+ results(query).map{ |r|
47
+ result = result_class.new(r)
48
+ result.cache_hit = @cache_hit if cache
49
+ result
50
+ }
51
+ end
52
+
53
+ ##
54
+ # Return the URL for a map of the given coordinates.
55
+ #
56
+ # Not necessarily implemented by all subclasses as only some lookups
57
+ # also provide maps.
58
+ #
59
+ def map_link_url(coordinates)
60
+ nil
61
+ end
62
+
63
+ ##
64
+ # Array containing string descriptions of keys required by the API.
65
+ # Empty array if keys are optional or not required.
66
+ #
67
+ def required_api_key_parts
68
+ []
69
+ end
70
+
71
+ ##
72
+ # URL to use for querying the geocoding engine.
73
+ #
74
+ # Subclasses should not modify this method. Instead they should define
75
+ # base_query_url and url_query_string. If absolutely necessary to
76
+ # subclss this method, they must also subclass #cache_key.
77
+ #
78
+ def query_url(query)
79
+ base_query_url(query) + url_query_string(query)
80
+ end
81
+
82
+ ##
83
+ # The working Cache object.
84
+ #
85
+ def cache
86
+ if @cache.nil? and store = configuration.cache
87
+ cache_options = configuration.cache_options
88
+ @cache = Cache.new(store, cache_options)
89
+ end
90
+ @cache
91
+ end
92
+
93
+ ##
94
+ # Array containing the protocols supported by the api.
95
+ # Should be set to [:http] if only HTTP is supported
96
+ # or [:https] if only HTTPS is supported.
97
+ #
98
+ def supported_protocols
99
+ [:http, :https]
100
+ end
101
+
102
+ private # -------------------------------------------------------------
103
+
104
+ ##
105
+ # String which, when concatenated with url_query_string(query)
106
+ # produces the full query URL. Should include the "?" a the end.
107
+ #
108
+ def base_query_url(query)
109
+ fail
110
+ end
111
+
112
+ ##
113
+ # An object with configuration data for this particular lookup.
114
+ #
115
+ def configuration
116
+ Geocoder.config_for_lookup(handle)
117
+ end
118
+
119
+ ##
120
+ # Object used to make HTTP requests.
121
+ #
122
+ def http_client
123
+ proxy_name = "#{protocol}_proxy"
124
+ if proxy = configuration.send(proxy_name)
125
+ proxy_url = !!(proxy =~ /^#{protocol}/) ? proxy : protocol + '://' + proxy
126
+ begin
127
+ uri = URI.parse(proxy_url)
128
+ rescue URI::InvalidURIError
129
+ raise ConfigurationError,
130
+ "Error parsing #{protocol.upcase} proxy URL: '#{proxy_url}'"
131
+ end
132
+ Net::HTTP::Proxy(uri.host, uri.port, uri.user, uri.password)
133
+ else
134
+ Net::HTTP
135
+ end
136
+ end
137
+
138
+ ##
139
+ # Geocoder::Result object or nil on timeout or other error.
140
+ #
141
+ def results(query)
142
+ fail
143
+ end
144
+
145
+ def query_url_params(query)
146
+ query.options[:params] || {}
147
+ end
148
+
149
+ def url_query_string(query)
150
+ hash_to_query(
151
+ query_url_params(query).reject{ |key,value| value.nil? }
152
+ )
153
+ end
154
+
155
+ ##
156
+ # Key to use for caching a geocoding result. Usually this will be the
157
+ # request URL, but in cases where OAuth is used and the nonce,
158
+ # timestamp, etc varies from one request to another, we need to use
159
+ # something else (like the URL before OAuth encoding).
160
+ #
161
+ def cache_key(query)
162
+ base_query_url(query) + hash_to_query(cache_key_params(query))
163
+ end
164
+
165
+ def cache_key_params(query)
166
+ # omit api_key and token because they may vary among requests
167
+ query_url_params(query).reject do |key,value|
168
+ key.to_s.match(/(key|token)/)
169
+ end
170
+ end
171
+
172
+ ##
173
+ # Class of the result objects
174
+ #
175
+ def result_class
176
+ Geocoder::Result.const_get(self.class.to_s.split(":").last)
177
+ end
178
+
179
+ ##
180
+ # Raise exception if configuration specifies it should be raised.
181
+ # Return false if exception not raised.
182
+ #
183
+ def raise_error(error, message = nil)
184
+ exceptions = configuration.always_raise
185
+ if exceptions == :all or exceptions.include?( error.is_a?(Class) ? error : error.class )
186
+ raise error, message
187
+ else
188
+ false
189
+ end
190
+ end
191
+
192
+ ##
193
+ # Returns a parsed search result (Ruby hash).
194
+ #
195
+ def fetch_data(query)
196
+ parse_raw_data fetch_raw_data(query)
197
+ rescue SocketError => err
198
+ raise_error(err) or Geocoder.log(:warn, "Geocoding API connection cannot be established.")
199
+ rescue Errno::ECONNREFUSED => err
200
+ raise_error(err) or Geocoder.log(:warn, "Geocoding API connection refused.")
201
+ rescue Geocoder::NetworkError => err
202
+ raise_error(err) or Geocoder.log(:warn, "Geocoding API connection is either unreacheable or reset by the peer")
203
+ rescue Timeout::Error => err
204
+ raise_error(err) or Geocoder.log(:warn, "Geocoding API not responding fast enough " +
205
+ "(use Geocoder.configure(:timeout => ...) to set limit).")
206
+ end
207
+
208
+ def parse_json(data)
209
+ if defined?(ActiveSupport::JSON)
210
+ ActiveSupport::JSON.decode(data)
211
+ else
212
+ JSON.parse(data)
213
+ end
214
+ rescue
215
+ unless raise_error(ResponseParseError.new(data))
216
+ Geocoder.log(:warn, "Geocoding API's response was not valid JSON")
217
+ Geocoder.log(:debug, "Raw response: #{data}")
218
+ end
219
+ end
220
+
221
+ ##
222
+ # Parses a raw search result (returns hash or array).
223
+ #
224
+ def parse_raw_data(raw_data)
225
+ parse_json(raw_data)
226
+ end
227
+
228
+ ##
229
+ # Protocol to use for communication with geocoding services.
230
+ # Set in configuration but not available for every service.
231
+ #
232
+ def protocol
233
+ "http" + (use_ssl? ? "s" : "")
234
+ end
235
+
236
+ def valid_response?(response)
237
+ (200..399).include?(response.code.to_i)
238
+ end
239
+
240
+ ##
241
+ # Fetch a raw geocoding result (JSON string).
242
+ # The result might or might not be cached.
243
+ #
244
+ def fetch_raw_data(query)
245
+ key = cache_key(query)
246
+ if cache and body = cache[key]
247
+ @cache_hit = true
248
+ else
249
+ check_api_key_configuration!(query)
250
+ response = make_api_request(query)
251
+ check_response_for_errors!(response)
252
+ body = response.body
253
+
254
+ # apply the charset from the Content-Type header, if possible
255
+ ct = response['content-type']
256
+
257
+ if ct && ct['charset']
258
+ charset = ct.split(';').select do |s|
259
+ s['charset']
260
+ end.first.to_s.split('=')
261
+ if charset.length == 2
262
+ body.force_encoding(charset.last) rescue ArgumentError
263
+ end
264
+ end
265
+
266
+ if cache and valid_response?(response)
267
+ cache[key] = body
268
+ end
269
+ @cache_hit = false
270
+ end
271
+ body
272
+ end
273
+
274
+ def check_response_for_errors!(response)
275
+ if response.code.to_i == 400
276
+ raise_error(Geocoder::InvalidRequest) ||
277
+ Geocoder.log(:warn, "Geocoding API error: 400 Bad Request")
278
+ elsif response.code.to_i == 401
279
+ raise_error(Geocoder::RequestDenied) ||
280
+ Geocoder.log(:warn, "Geocoding API error: 401 Unauthorized")
281
+ elsif response.code.to_i == 402
282
+ raise_error(Geocoder::OverQueryLimitError) ||
283
+ Geocoder.log(:warn, "Geocoding API error: 402 Payment Required")
284
+ elsif response.code.to_i == 429
285
+ raise_error(Geocoder::OverQueryLimitError) ||
286
+ Geocoder.log(:warn, "Geocoding API error: 429 Too Many Requests")
287
+ elsif response.code.to_i == 503
288
+ raise_error(Geocoder::ServiceUnavailable) ||
289
+ Geocoder.log(:warn, "Geocoding API error: 503 Service Unavailable")
290
+ end
291
+ end
292
+
293
+ ##
294
+ # Make an HTTP(S) request to a geocoding API and
295
+ # return the response object.
296
+ #
297
+ def make_api_request(query)
298
+ uri = URI.parse(query_url(query))
299
+ Geocoder.log(:debug, "Geocoder: HTTP request being made for #{uri.to_s}")
300
+ http_client.start(uri.host, uri.port, use_ssl: use_ssl?, open_timeout: configuration.timeout, read_timeout: configuration.timeout) do |client|
301
+ configure_ssl!(client) if use_ssl?
302
+ req = Net::HTTP::Get.new(uri.request_uri, configuration.http_headers)
303
+ if configuration.basic_auth[:user] and configuration.basic_auth[:password]
304
+ req.basic_auth(
305
+ configuration.basic_auth[:user],
306
+ configuration.basic_auth[:password]
307
+ )
308
+ end
309
+ client.request(req)
310
+ end
311
+ rescue Timeout::Error
312
+ raise Geocoder::LookupTimeout
313
+ rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ENETUNREACH, Errno::ECONNRESET
314
+ raise Geocoder::NetworkError
315
+ end
316
+
317
+ def use_ssl?
318
+ if supported_protocols == [:https]
319
+ true
320
+ elsif supported_protocols == [:http]
321
+ false
322
+ else
323
+ configuration.use_https
324
+ end
325
+ end
326
+
327
+ def configure_ssl!(client); end
328
+
329
+ def check_api_key_configuration!(query)
330
+ key_parts = query.lookup.required_api_key_parts
331
+ if key_parts.size > Array(configuration.api_key).size
332
+ parts_string = key_parts.size == 1 ? key_parts.first : key_parts
333
+ raise Geocoder::ConfigurationError,
334
+ "The #{query.lookup.name} API requires a key to be configured: " +
335
+ parts_string.inspect
336
+ end
337
+ end
338
+
339
+ ##
340
+ # Simulate ActiveSupport's Object#to_query.
341
+ # Removes any keys with nil value.
342
+ #
343
+ def hash_to_query(hash)
344
+ require 'cgi' unless defined?(CGI) && defined?(CGI.escape)
345
+ hash.collect{ |p|
346
+ p[1].nil? ? nil : p.map{ |i| CGI.escape i.to_s } * '='
347
+ }.compact.sort * '&'
348
+ end
349
+ end
350
+ end
351
+ end
@@ -0,0 +1,82 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/bing"
3
+
4
+ module Geocoder::Lookup
5
+ class Bing < Base
6
+
7
+ def name
8
+ "Bing"
9
+ end
10
+
11
+ def map_link_url(coordinates)
12
+ "http://www.bing.com/maps/default.aspx?cp=#{coordinates.join('~')}"
13
+ end
14
+
15
+ def required_api_key_parts
16
+ ["key"]
17
+ end
18
+
19
+ private # ---------------------------------------------------------------
20
+
21
+ def base_query_url(query)
22
+ text = ERB::Util.url_encode(query.sanitized_text.strip)
23
+ url = "#{protocol}://dev.virtualearth.net/REST/v1/Locations/"
24
+ if query.reverse_geocode?
25
+ url + "#{text}?"
26
+ else
27
+ if r = query.options[:region]
28
+ url << "#{r}/"
29
+ end
30
+ # use the more forgiving 'unstructured' query format to allow special
31
+ # chars, newlines, brackets, typos.
32
+ url + "?q=#{text}&"
33
+ end
34
+ end
35
+
36
+ def results(query)
37
+ return [] unless doc = fetch_data(query)
38
+
39
+ if doc['statusCode'] == 200
40
+ return doc['resourceSets'].first['estimatedTotal'] > 0 ? doc['resourceSets'].first['resources'] : []
41
+ elsif doc['statusCode'] == 401 and doc["authenticationResultCode"] == "InvalidCredentials"
42
+ raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid Bing API key.")
43
+ elsif doc['statusCode'] == 403
44
+ raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Bing Geocoding API error: Forbidden Request")
45
+ elsif [500, 503].include?(doc['statusCode'])
46
+ raise_error(Geocoder::ServiceUnavailable) ||
47
+ Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
48
+ else
49
+ Geocoder.log(:warn, "Bing Geocoding API error: #{doc['statusCode']} (#{doc['statusDescription']}).")
50
+ end
51
+ return []
52
+ end
53
+
54
+ def query_url_params(query)
55
+ {
56
+ key: configuration.api_key,
57
+ culture: (query.language || configuration.language)
58
+ }.merge(super)
59
+ end
60
+
61
+ def check_response_for_errors!(response)
62
+ super
63
+ if server_overloaded?(response)
64
+ raise_error(Geocoder::ServiceUnavailable) ||
65
+ Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
66
+ end
67
+ end
68
+
69
+ def valid_response?(response)
70
+ super(response) and not server_overloaded?(response)
71
+ end
72
+
73
+ def server_overloaded?(response)
74
+ # Occasionally, the servers processing service requests can be overloaded,
75
+ # and you may receive some responses that contain no results for queries that
76
+ # you would normally receive a result. To identify this situation,
77
+ # check the HTTP headers of the response. If the HTTP header X-MS-BM-WS-INFO is set to 1,
78
+ # it is best to wait a few seconds and try again.
79
+ response['x-ms-bm-ws-info'].to_i == 1
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,52 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/db_ip_com'
3
+
4
+ module Geocoder::Lookup
5
+ class DbIpCom < Base
6
+
7
+ def name
8
+ 'DB-IP.com'
9
+ end
10
+
11
+ def supported_protocols
12
+ [:https, :http]
13
+ end
14
+
15
+ def required_api_key_parts
16
+ ['api_key']
17
+ end
18
+
19
+ private # ----------------------------------------------------------------
20
+
21
+ def base_query_url(query)
22
+ "#{protocol}://api.db-ip.com/v2/#{configuration.api_key}/#{query.sanitized_text}?"
23
+ end
24
+
25
+ ##
26
+ # Same as query_url but without the api key.
27
+ #
28
+ def cache_key(query)
29
+ "#{protocol}://api.db-ip.com/v2/#{query.sanitized_text}?" + hash_to_query(cache_key_params(query))
30
+ end
31
+
32
+ def results(query)
33
+ return [] unless (doc = fetch_data(query))
34
+
35
+ case doc['error']
36
+ when 'maximum number of queries per day exceeded'
37
+ raise_error Geocoder::OverQueryLimitError ||
38
+ Geocoder.log(:warn, 'DB-API query limit exceeded.')
39
+
40
+ when 'invalid API key'
41
+ raise_error Geocoder::InvalidApiKey ||
42
+ Geocoder.log(:warn, 'Invalid DB-IP API key.')
43
+ when nil
44
+ [doc]
45
+
46
+ else
47
+ raise_error Geocoder::Error ||
48
+ Geocoder.log(:warn, "Request failed: #{doc['error']}")
49
+ end
50
+ end
51
+ end
52
+ end