geocoder 1.2.6 → 1.6.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 (276) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +189 -1
  3. data/LICENSE +1 -1
  4. data/README.md +387 -755
  5. data/examples/autoexpire_cache_redis.rb +5 -3
  6. data/examples/reverse_geocode_job.rb +40 -0
  7. data/lib/generators/geocoder/config/templates/initializer.rb +17 -16
  8. data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +2 -0
  9. data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +2 -0
  10. data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +1 -1
  11. data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +1 -1
  12. data/lib/generators/geocoder/migration_version.rb +15 -0
  13. data/lib/geocoder/cache.rb +6 -2
  14. data/lib/geocoder/calculations.rb +30 -38
  15. data/lib/geocoder/cli.rb +2 -2
  16. data/lib/geocoder/configuration.rb +18 -5
  17. data/lib/geocoder/esri_token.rb +38 -0
  18. data/lib/geocoder/exceptions.rb +19 -0
  19. data/lib/geocoder/ip_address.rb +16 -11
  20. data/lib/geocoder/kernel_logger.rb +25 -0
  21. data/lib/geocoder/logger.rb +47 -0
  22. data/lib/geocoder/lookup.rb +31 -12
  23. data/lib/geocoder/lookups/amap.rb +63 -0
  24. data/lib/geocoder/lookups/baidu.rb +17 -9
  25. data/lib/geocoder/lookups/baidu_ip.rb +7 -31
  26. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +143 -0
  27. data/lib/geocoder/lookups/base.rb +73 -25
  28. data/lib/geocoder/lookups/bing.rb +38 -15
  29. data/lib/geocoder/lookups/db_ip_com.rb +52 -0
  30. data/lib/geocoder/lookups/dstk.rb +4 -2
  31. data/lib/geocoder/lookups/esri.rb +55 -8
  32. data/lib/geocoder/lookups/freegeoip.rb +18 -5
  33. data/lib/geocoder/lookups/geocoder_ca.rb +5 -6
  34. data/lib/geocoder/lookups/geocodio.rb +8 -8
  35. data/lib/geocoder/lookups/geoip2.rb +10 -5
  36. data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
  37. data/lib/geocoder/lookups/google.rb +37 -9
  38. data/lib/geocoder/lookups/google_places_details.rb +9 -9
  39. data/lib/geocoder/lookups/google_places_search.rb +33 -0
  40. data/lib/geocoder/lookups/google_premier.rb +11 -1
  41. data/lib/geocoder/lookups/here.rb +29 -23
  42. data/lib/geocoder/lookups/ip2location.rb +67 -0
  43. data/lib/geocoder/lookups/ipapi_com.rb +82 -0
  44. data/lib/geocoder/lookups/ipdata_co.rb +62 -0
  45. data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  46. data/lib/geocoder/lookups/ipinfo_io.rb +44 -0
  47. data/lib/geocoder/lookups/ipregistry.rb +68 -0
  48. data/lib/geocoder/lookups/ipstack.rb +63 -0
  49. data/lib/geocoder/lookups/latlon.rb +59 -0
  50. data/lib/geocoder/lookups/location_iq.rb +50 -0
  51. data/lib/geocoder/lookups/mapbox.rb +59 -0
  52. data/lib/geocoder/lookups/mapquest.rb +7 -9
  53. data/lib/geocoder/lookups/maxmind.rb +7 -7
  54. data/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
  55. data/lib/geocoder/lookups/maxmind_local.rb +9 -2
  56. data/lib/geocoder/lookups/nominatim.rb +18 -6
  57. data/lib/geocoder/lookups/opencagedata.rb +16 -9
  58. data/lib/geocoder/lookups/osmnames.rb +57 -0
  59. data/lib/geocoder/lookups/pelias.rb +63 -0
  60. data/lib/geocoder/lookups/pickpoint.rb +41 -0
  61. data/lib/geocoder/lookups/pointpin.rb +14 -13
  62. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +7 -8
  63. data/lib/geocoder/lookups/postcodes_io.rb +31 -0
  64. data/lib/geocoder/lookups/smarty_streets.rb +23 -5
  65. data/lib/geocoder/lookups/telize.rb +42 -7
  66. data/lib/geocoder/lookups/tencent.rb +59 -0
  67. data/lib/geocoder/lookups/yandex.rb +17 -9
  68. data/lib/geocoder/models/active_record.rb +4 -3
  69. data/lib/geocoder/models/mongo_base.rb +0 -2
  70. data/lib/geocoder/query.rb +15 -1
  71. data/lib/geocoder/railtie.rb +1 -1
  72. data/lib/geocoder/request.rb +103 -14
  73. data/lib/geocoder/results/amap.rb +87 -0
  74. data/lib/geocoder/results/baidu.rb +10 -14
  75. data/lib/geocoder/results/ban_data_gouv_fr.rb +257 -0
  76. data/lib/geocoder/results/base.rb +13 -1
  77. data/lib/geocoder/results/bing.rb +5 -1
  78. data/lib/geocoder/results/db_ip_com.rb +58 -0
  79. data/lib/geocoder/results/esri.rb +30 -6
  80. data/lib/geocoder/results/freegeoip.rb +2 -7
  81. data/lib/geocoder/results/geocoder_ca.rb +3 -3
  82. data/lib/geocoder/results/geocodio.rb +15 -3
  83. data/lib/geocoder/results/geoip2.rb +37 -25
  84. data/lib/geocoder/results/geoportail_lu.rb +71 -0
  85. data/lib/geocoder/results/google.rb +26 -0
  86. data/lib/geocoder/results/google_places_details.rb +4 -0
  87. data/lib/geocoder/results/google_places_search.rb +52 -0
  88. data/lib/geocoder/results/here.rb +21 -1
  89. data/lib/geocoder/results/ip2location.rb +22 -0
  90. data/lib/geocoder/results/ipapi_com.rb +45 -0
  91. data/lib/geocoder/results/ipdata_co.rb +40 -0
  92. data/lib/geocoder/results/ipgeolocation.rb +59 -0
  93. data/lib/geocoder/results/ipinfo_io.rb +48 -0
  94. data/lib/geocoder/results/ipregistry.rb +308 -0
  95. data/lib/geocoder/results/ipstack.rb +60 -0
  96. data/lib/geocoder/results/latlon.rb +71 -0
  97. data/lib/geocoder/results/location_iq.rb +6 -0
  98. data/lib/geocoder/results/mapbox.rb +57 -0
  99. data/lib/geocoder/results/mapquest.rb +5 -8
  100. data/lib/geocoder/results/maxmind.rb +0 -5
  101. data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
  102. data/lib/geocoder/results/maxmind_local.rb +0 -5
  103. data/lib/geocoder/results/nominatim.rb +18 -3
  104. data/lib/geocoder/results/opencagedata.rb +20 -2
  105. data/lib/geocoder/results/osmnames.rb +56 -0
  106. data/lib/geocoder/results/pelias.rb +58 -0
  107. data/lib/geocoder/results/pickpoint.rb +6 -0
  108. data/lib/geocoder/results/pointpin.rb +0 -4
  109. data/lib/geocoder/results/postcodes_io.rb +40 -0
  110. data/lib/geocoder/results/smarty_streets.rb +55 -19
  111. data/lib/geocoder/results/telize.rb +0 -5
  112. data/lib/geocoder/results/tencent.rb +72 -0
  113. data/lib/geocoder/results/test.rb +1 -1
  114. data/lib/geocoder/results/yandex.rb +57 -7
  115. data/lib/geocoder/sql.rb +9 -6
  116. data/lib/geocoder/stores/active_record.rb +49 -10
  117. data/lib/geocoder/stores/base.rb +2 -14
  118. data/lib/geocoder/stores/mongo_base.rb +0 -31
  119. data/lib/geocoder/version.rb +1 -1
  120. data/lib/geocoder.rb +2 -1
  121. data/lib/hash_recursive_merge.rb +1 -2
  122. data/lib/maxmind_database.rb +4 -4
  123. data/lib/tasks/geocoder.rake +29 -4
  124. metadata +56 -159
  125. data/.gitignore +0 -6
  126. data/.travis.yml +0 -31
  127. data/Rakefile +0 -25
  128. data/gemfiles/Gemfile.mongoid-2.4.x +0 -16
  129. data/lib/geocoder/lookups/geocoder_us.rb +0 -39
  130. data/lib/geocoder/lookups/okf.rb +0 -43
  131. data/lib/geocoder/lookups/ovi.rb +0 -62
  132. data/lib/geocoder/lookups/yahoo.rb +0 -88
  133. data/lib/geocoder/results/geocoder_us.rb +0 -39
  134. data/lib/geocoder/results/okf.rb +0 -106
  135. data/lib/geocoder/results/ovi.rb +0 -62
  136. data/lib/geocoder/results/yahoo.rb +0 -55
  137. data/lib/oauth_util.rb +0 -112
  138. data/test/fixtures/baidu_invalid_key +0 -1
  139. data/test/fixtures/baidu_ip_202_198_16_3 +0 -19
  140. data/test/fixtures/baidu_ip_invalid_key +0 -1
  141. data/test/fixtures/baidu_ip_no_results +0 -1
  142. data/test/fixtures/baidu_no_results +0 -1
  143. data/test/fixtures/baidu_reverse +0 -1
  144. data/test/fixtures/baidu_shanghai_pearl_tower +0 -12
  145. data/test/fixtures/bing_invalid_key +0 -1
  146. data/test/fixtures/bing_madison_square_garden +0 -40
  147. data/test/fixtures/bing_no_results +0 -16
  148. data/test/fixtures/bing_reverse +0 -42
  149. data/test/fixtures/cloudmade_invalid_key +0 -1
  150. data/test/fixtures/cloudmade_madison_square_garden +0 -1
  151. data/test/fixtures/cloudmade_no_results +0 -1
  152. data/test/fixtures/esri_madison_square_garden +0 -59
  153. data/test/fixtures/esri_no_results +0 -8
  154. data/test/fixtures/esri_reverse +0 -21
  155. data/test/fixtures/freegeoip_74_200_247_59 +0 -12
  156. data/test/fixtures/freegeoip_no_results +0 -1
  157. data/test/fixtures/geocoder_ca_madison_square_garden +0 -1
  158. data/test/fixtures/geocoder_ca_no_results +0 -1
  159. data/test/fixtures/geocoder_ca_reverse +0 -34
  160. data/test/fixtures/geocoder_us_madison_square_garden +0 -1
  161. data/test/fixtures/geocoder_us_no_results +0 -1
  162. data/test/fixtures/geocodio_1101_pennsylvania_ave +0 -1
  163. data/test/fixtures/geocodio_bad_api_key +0 -3
  164. data/test/fixtures/geocodio_invalid +0 -4
  165. data/test/fixtures/geocodio_no_results +0 -1
  166. data/test/fixtures/geocodio_over_query_limit +0 -4
  167. data/test/fixtures/google_garbage +0 -456
  168. data/test/fixtures/google_madison_square_garden +0 -57
  169. data/test/fixtures/google_no_city_data +0 -44
  170. data/test/fixtures/google_no_locality +0 -51
  171. data/test/fixtures/google_no_results +0 -4
  172. data/test/fixtures/google_over_limit +0 -4
  173. data/test/fixtures/google_places_details_invalid_request +0 -4
  174. data/test/fixtures/google_places_details_madison_square_garden +0 -120
  175. data/test/fixtures/google_places_details_no_results +0 -4
  176. data/test/fixtures/google_places_details_no_reviews +0 -60
  177. data/test/fixtures/google_places_details_no_types +0 -66
  178. data/test/fixtures/here_madison_square_garden +0 -72
  179. data/test/fixtures/here_no_results +0 -8
  180. data/test/fixtures/mapquest_error +0 -16
  181. data/test/fixtures/mapquest_invalid_api_key +0 -16
  182. data/test/fixtures/mapquest_invalid_request +0 -16
  183. data/test/fixtures/mapquest_madison_square_garden +0 -52
  184. data/test/fixtures/mapquest_no_results +0 -16
  185. data/test/fixtures/maxmind_24_24_24_21 +0 -1
  186. data/test/fixtures/maxmind_24_24_24_22 +0 -1
  187. data/test/fixtures/maxmind_24_24_24_23 +0 -1
  188. data/test/fixtures/maxmind_24_24_24_24 +0 -1
  189. data/test/fixtures/maxmind_74_200_247_59 +0 -1
  190. data/test/fixtures/maxmind_invalid_key +0 -1
  191. data/test/fixtures/maxmind_no_results +0 -1
  192. data/test/fixtures/nominatim_madison_square_garden +0 -150
  193. data/test/fixtures/nominatim_no_results +0 -1
  194. data/test/fixtures/nominatim_over_limit +0 -1
  195. data/test/fixtures/okf_kirstinmaki +0 -67
  196. data/test/fixtures/okf_no_results +0 -4
  197. data/test/fixtures/opencagedata_invalid_api_key +0 -25
  198. data/test/fixtures/opencagedata_invalid_request +0 -26
  199. data/test/fixtures/opencagedata_madison_square_garden +0 -73
  200. data/test/fixtures/opencagedata_no_results +0 -29
  201. data/test/fixtures/opencagedata_over_limit +0 -31
  202. data/test/fixtures/ovi_madison_square_garden +0 -72
  203. data/test/fixtures/ovi_no_results +0 -8
  204. data/test/fixtures/pointpin_10_10_10_10 +0 -1
  205. data/test/fixtures/pointpin_555_555_555_555 +0 -1
  206. data/test/fixtures/pointpin_80_111_555_555 +0 -1
  207. data/test/fixtures/pointpin_no_results +0 -1
  208. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_WR26NJ +0 -1
  209. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_generic_error +0 -1
  210. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_hampshire +0 -1
  211. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_key_limit_exceeded +0 -1
  212. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_no_results +0 -1
  213. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_romsey +0 -1
  214. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_unknown_key +0 -1
  215. data/test/fixtures/smarty_streets_11211 +0 -1
  216. data/test/fixtures/smarty_streets_madison_square_garden +0 -47
  217. data/test/fixtures/smarty_streets_no_results +0 -1
  218. data/test/fixtures/telize_10_10_10_10 +0 -1
  219. data/test/fixtures/telize_555_555_555_555 +0 -4
  220. data/test/fixtures/telize_74_200_247_59 +0 -1
  221. data/test/fixtures/telize_no_results +0 -1
  222. data/test/fixtures/yahoo_error +0 -1
  223. data/test/fixtures/yahoo_invalid_key +0 -2
  224. data/test/fixtures/yahoo_madison_square_garden +0 -52
  225. data/test/fixtures/yahoo_no_results +0 -10
  226. data/test/fixtures/yahoo_over_limit +0 -2
  227. data/test/fixtures/yandex_canada_rue_dupuis_14 +0 -446
  228. data/test/fixtures/yandex_invalid_key +0 -1
  229. data/test/fixtures/yandex_kremlin +0 -48
  230. data/test/fixtures/yandex_new_york +0 -1
  231. data/test/fixtures/yandex_no_city_and_town +0 -112
  232. data/test/fixtures/yandex_no_results +0 -16
  233. data/test/integration/http_client_test.rb +0 -31
  234. data/test/mongoid_test_helper.rb +0 -43
  235. data/test/test_helper.rb +0 -416
  236. data/test/unit/active_record_test.rb +0 -16
  237. data/test/unit/cache_test.rb +0 -37
  238. data/test/unit/calculations_test.rb +0 -220
  239. data/test/unit/configuration_test.rb +0 -55
  240. data/test/unit/error_handling_test.rb +0 -56
  241. data/test/unit/geocoder_test.rb +0 -78
  242. data/test/unit/https_test.rb +0 -17
  243. data/test/unit/ip_address_test.rb +0 -27
  244. data/test/unit/lookup_test.rb +0 -153
  245. data/test/unit/lookups/bing_test.rb +0 -68
  246. data/test/unit/lookups/dstk_test.rb +0 -26
  247. data/test/unit/lookups/esri_test.rb +0 -48
  248. data/test/unit/lookups/freegeoip_test.rb +0 -27
  249. data/test/unit/lookups/geocoder_ca_test.rb +0 -17
  250. data/test/unit/lookups/geocodio_test.rb +0 -55
  251. data/test/unit/lookups/geoip2_test.rb +0 -27
  252. data/test/unit/lookups/google_places_details_test.rb +0 -122
  253. data/test/unit/lookups/google_premier_test.rb +0 -22
  254. data/test/unit/lookups/google_test.rb +0 -84
  255. data/test/unit/lookups/mapquest_test.rb +0 -60
  256. data/test/unit/lookups/maxmind_local_test.rb +0 -28
  257. data/test/unit/lookups/maxmind_test.rb +0 -63
  258. data/test/unit/lookups/nominatim_test.rb +0 -31
  259. data/test/unit/lookups/okf_test.rb +0 -38
  260. data/test/unit/lookups/opencagedata_test.rb +0 -64
  261. data/test/unit/lookups/pointpin_test.rb +0 -30
  262. data/test/unit/lookups/postcode_anywhere_uk_test.rb +0 -70
  263. data/test/unit/lookups/smarty_streets_test.rb +0 -71
  264. data/test/unit/lookups/telize_test.rb +0 -36
  265. data/test/unit/lookups/yahoo_test.rb +0 -35
  266. data/test/unit/method_aliases_test.rb +0 -26
  267. data/test/unit/model_test.rb +0 -38
  268. data/test/unit/mongoid_test.rb +0 -47
  269. data/test/unit/near_test.rb +0 -87
  270. data/test/unit/oauth_util_test.rb +0 -31
  271. data/test/unit/proxy_test.rb +0 -37
  272. data/test/unit/query_test.rb +0 -52
  273. data/test/unit/rake_task_test.rb +0 -21
  274. data/test/unit/request_test.rb +0 -35
  275. data/test/unit/result_test.rb +0 -72
  276. data/test/unit/test_mode_test.rb +0 -70
@@ -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
@@ -12,9 +12,11 @@ module Geocoder::Lookup
12
12
  "Data Science Toolkit"
13
13
  end
14
14
 
15
- def query_url(query)
15
+ private # ----------------------------------------------------------------
16
+
17
+ def base_query_url(query)
16
18
  host = configuration[:host] || "www.datasciencetoolkit.org"
17
- "#{protocol}://#{host}/maps/api/geocode/json?" + url_query_string(query)
19
+ "#{protocol}://#{host}/maps/api/geocode/json?"
18
20
  end
19
21
  end
20
22
  end
@@ -1,27 +1,26 @@
1
1
  require 'geocoder/lookups/base'
2
2
  require "geocoder/results/esri"
3
+ require 'geocoder/esri_token'
3
4
 
4
5
  module Geocoder::Lookup
5
6
  class Esri < Base
6
-
7
+
7
8
  def name
8
9
  "Esri"
9
10
  end
10
11
 
11
- def query_url(query)
12
- search_keyword = query.reverse_geocode? ? "reverseGeocode" : "find"
12
+ private # ---------------------------------------------------------------
13
13
 
14
- "#{protocol}://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/#{search_keyword}?" +
15
- url_query_string(query)
14
+ def base_query_url(query)
15
+ action = query.reverse_geocode? ? "reverseGeocode" : "find"
16
+ "#{protocol}://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/#{action}?"
16
17
  end
17
18
 
18
- private # ---------------------------------------------------------------
19
-
20
19
  def results(query)
21
20
  return [] unless doc = fetch_data(query)
22
21
 
23
22
  if (!query.reverse_geocode?)
24
- return [] if doc['locations'].empty?
23
+ return [] if !doc['locations'] || doc['locations'].empty?
25
24
  end
26
25
 
27
26
  if (doc['error'].nil?)
@@ -41,8 +40,56 @@ module Geocoder::Lookup
41
40
  else
42
41
  params[:text] = query.sanitized_text
43
42
  end
43
+
44
+ params[:token] = token(query)
45
+
46
+ if for_storage_value = for_storage(query)
47
+ params[:forStorage] = for_storage_value
48
+ end
49
+ params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
44
50
  params.merge(super)
45
51
  end
46
52
 
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?
73
+ end
74
+
75
+ def valid_token_configured?(token_instance)
76
+ !token_instance.nil? && token_instance.active?
77
+ end
78
+
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
89
+ end
90
+
91
+ def create_token
92
+ Geocoder::EsriToken.generate_token(*configuration.api_key)
93
+ end
47
94
  end
48
95
  end
@@ -8,19 +8,32 @@ module Geocoder::Lookup
8
8
  "FreeGeoIP"
9
9
  end
10
10
 
11
+ def supported_protocols
12
+ if configuration[:host]
13
+ [:https]
14
+ else
15
+ # use https for default host
16
+ [:https]
17
+ end
18
+ end
19
+
11
20
  def query_url(query)
12
21
  "#{protocol}://#{host}/json/#{query.sanitized_text}"
13
22
  end
14
23
 
15
24
  private # ---------------------------------------------------------------
16
25
 
26
+ def cache_key(query)
27
+ query_url(query)
28
+ end
29
+
17
30
  def parse_raw_data(raw_data)
18
31
  raw_data.match(/^<html><title>404/) ? nil : super(raw_data)
19
32
  end
20
33
 
21
34
  def results(query)
22
- # don't look up a loopback address, just return the stored result
23
- 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?
24
37
  # note: Freegeoip.net returns plain text "Not Found" on bad request
25
38
  (doc = fetch_data(query)) ? [doc] : []
26
39
  end
@@ -31,8 +44,8 @@ module Geocoder::Lookup
31
44
  "city" => "",
32
45
  "region_code" => "",
33
46
  "region_name" => "",
34
- "metrocode" => "",
35
- "zipcode" => "",
47
+ "metro_code" => "",
48
+ "zip_code" => "",
36
49
  "latitude" => "0",
37
50
  "longitude" => "0",
38
51
  "country_name" => "Reserved",
@@ -41,7 +54,7 @@ module Geocoder::Lookup
41
54
  end
42
55
 
43
56
  def host
44
- configuration[:host] || "freegeoip.net"
57
+ configuration[:host] || "freegeoip.app"
45
58
  end
46
59
  end
47
60
  end
@@ -8,12 +8,12 @@ module Geocoder::Lookup
8
8
  "Geocoder.ca"
9
9
  end
10
10
 
11
- def query_url(query)
12
- "#{protocol}://geocoder.ca/?" + url_query_string(query)
13
- end
14
-
15
11
  private # ---------------------------------------------------------------
16
12
 
13
+ def base_query_url(query)
14
+ "#{protocol}://geocoder.ca/?"
15
+ end
16
+
17
17
  def results(query)
18
18
  return [] unless doc = fetch_data(query)
19
19
  if doc['error'].nil?
@@ -21,7 +21,7 @@ module Geocoder::Lookup
21
21
  elsif doc['error']['code'] == "005"
22
22
  # "Postal Code is not in the proper Format" => no results, just shut up
23
23
  else
24
- warn "Geocoder.ca service error: #{doc['error']['code']} (#{doc['error']['description']})."
24
+ Geocoder.log(:warn, "Geocoder.ca service error: #{doc['error']['code']} (#{doc['error']['description']}).")
25
25
  end
26
26
  return []
27
27
  end
@@ -51,4 +51,3 @@ module Geocoder::Lookup
51
51
  end
52
52
  end
53
53
  end
54
-
@@ -8,30 +8,30 @@ module Geocoder::Lookup
8
8
  "Geocodio"
9
9
  end
10
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
11
  def results(query)
17
12
  return [] unless doc = fetch_data(query)
18
13
  return doc["results"] if doc['error'].nil?
19
14
 
20
15
  if doc['error'] == 'Invalid API key'
21
16
  raise_error(Geocoder::InvalidApiKey) ||
22
- warn("Geocodio service error: invalid API key.")
17
+ Geocoder.log(:warn, "Geocodio service error: invalid API key.")
23
18
  elsif doc['error'].match(/You have reached your daily maximum/)
24
19
  raise_error(Geocoder::OverQueryLimitError, doc['error']) ||
25
- warn("Geocodio service error: #{doc['error']}.")
20
+ Geocoder.log(:warn, "Geocodio service error: #{doc['error']}.")
26
21
  else
27
22
  raise_error(Geocoder::InvalidRequest, doc['error']) ||
28
- warn("Geocodio service error: #{doc['error']}.")
23
+ Geocoder.log(:warn, "Geocodio service error: #{doc['error']}.")
29
24
  end
30
25
  []
31
26
  end
32
27
 
33
28
  private # ---------------------------------------------------------------
34
29
 
30
+ def base_query_url(query)
31
+ path = query.reverse_geocode? ? "reverse" : "geocode"
32
+ "#{protocol}://api.geocod.io/v1.3/#{path}?"
33
+ end
34
+
35
35
  def query_url_params(query)
36
36
  {
37
37
  :api_key => configuration.api_key,
@@ -4,6 +4,8 @@ require 'geocoder/results/geoip2'
4
4
  module Geocoder
5
5
  module Lookup
6
6
  class Geoip2 < Base
7
+ attr_reader :gem_name
8
+
7
9
  def initialize
8
10
  unless configuration[:file].nil?
9
11
  begin
@@ -12,6 +14,8 @@ module Geocoder
12
14
  rescue LoadError
13
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."
14
16
  end
17
+
18
+ @mmdb = db_class.new(configuration[:file].to_s)
15
19
  end
16
20
  super
17
21
  end
@@ -26,13 +30,14 @@ module Geocoder
26
30
 
27
31
  private
28
32
 
33
+ def db_class
34
+ gem_name == 'hive_geoip2' ? Hive::GeoIP2 : MaxMindDB
35
+ end
36
+
29
37
  def results(query)
30
38
  return [] unless configuration[:file]
31
- if @gem_name == 'hive_geoip2'
32
- result = Hive::GeoIP2.lookup(query.to_s, configuration[:file].to_s)
33
- else
34
- result = MaxMindDB.new(configuration[:file].to_s).lookup(query.to_s)
35
- end
39
+
40
+ result = @mmdb.lookup(query.to_s)
36
41
  result.nil? ? [] : [result]
37
42
  end
38
43
  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
+ private # ---------------------------------------------------------------
13
+
14
+ def base_query_url(query)
15
+ if query.reverse_geocode?
16
+ reverse_geocode_url_base_path
17
+ else
18
+ search_url_base_path
19
+ end
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
@@ -12,14 +12,35 @@ module Geocoder::Lookup
12
12
  "http://maps.google.com/maps?q=#{coordinates.join(',')}"
13
13
  end
14
14
 
15
- def query_url(query)
16
- "#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + url_query_string(query)
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
17
22
  end
18
23
 
19
24
  private # ---------------------------------------------------------------
20
25
 
26
+ def base_query_url(query)
27
+ "#{protocol}://maps.googleapis.com/maps/api/geocode/json?"
28
+ end
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
+
21
41
  def valid_response?(response)
22
- status = parse_json(response.body)["status"]
42
+ json = parse_json(response.body)
43
+ status = json["status"] if json
23
44
  super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
24
45
  end
25
46
 
@@ -29,23 +50,27 @@ module Geocoder::Lookup
29
50
  return doc['results']
30
51
  when "OVER_QUERY_LIMIT"
31
52
  raise_error(Geocoder::OverQueryLimitError) ||
32
- warn("Google Geocoding API error: over query limit.")
53
+ Geocoder.log(:warn, "#{name} API error: over query limit.")
33
54
  when "REQUEST_DENIED"
34
- raise_error(Geocoder::RequestDenied) ||
35
- warn("Google Geocoding API error: request denied.")
55
+ raise_error(Geocoder::RequestDenied, doc['error_message']) ||
56
+ Geocoder.log(:warn, "#{name} API error: request denied (#{doc['error_message']}).")
36
57
  when "INVALID_REQUEST"
37
- raise_error(Geocoder::InvalidRequest) ||
38
- warn("Google Geocoding API error: invalid request.")
58
+ raise_error(Geocoder::InvalidRequest, doc['error_message']) ||
59
+ Geocoder.log(:warn, "#{name} API error: invalid request (#{doc['error_message']}).")
39
60
  end
40
61
  return []
41
62
  end
42
63
 
43
64
  def query_url_google_params(query)
44
65
  params = {
45
- (query.reverse_geocode? ? :latlng : :address) => query.sanitized_text,
46
66
  :sensor => "false",
47
67
  :language => (query.language || configuration.language)
48
68
  }
69
+ if query.options[:google_place_id]
70
+ params[:place_id] = query.sanitized_text
71
+ else
72
+ params[(query.reverse_geocode? ? :latlng : :address)] = query.sanitized_text
73
+ end
49
74
  unless (bounds = query.options[:bounds]).nil?
50
75
  params[:bounds] = bounds.map{ |point| "%f,%f" % point }.join('|')
51
76
  end
@@ -55,6 +80,9 @@ module Geocoder::Lookup
55
80
  unless (components = query.options[:components]).nil?
56
81
  params[:components] = components.is_a?(Array) ? components.join("|") : components
57
82
  end
83
+ unless (result_type = query.options[:result_type]).nil?
84
+ params[:result_type] = result_type.is_a?(Array) ? result_type.join("|") : result_type
85
+ end
58
86
  params
59
87
  end
60
88
 
@@ -12,16 +12,16 @@ module Geocoder
12
12
  ["key"]
13
13
  end
14
14
 
15
- def use_ssl?
16
- true
17
- end
18
-
19
- def query_url(query)
20
- "#{protocol}://maps.googleapis.com/maps/api/place/details/json?#{url_query_string(query)}"
15
+ def supported_protocols
16
+ [:https]
21
17
  end
22
18
 
23
19
  private
24
20
 
21
+ def base_query_url(query)
22
+ "#{protocol}://maps.googleapis.com/maps/api/place/details/json?"
23
+ end
24
+
25
25
  def results(query)
26
26
  return [] unless doc = fetch_data(query)
27
27
 
@@ -29,11 +29,11 @@ module Geocoder
29
29
  when "OK"
30
30
  return [doc["result"]]
31
31
  when "OVER_QUERY_LIMIT"
32
- raise_error(Geocoder::OverQueryLimitError) || warn("Google Places Details API error: over query limit.")
32
+ raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Google Places Details API error: over query limit.")
33
33
  when "REQUEST_DENIED"
34
- raise_error(Geocoder::RequestDenied) || warn("Google Places Details API error: request denied.")
34
+ raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Google Places Details API error: request denied.")
35
35
  when "INVALID_REQUEST"
36
- raise_error(Geocoder::InvalidRequest) || warn("Google Places Details API error: invalid request.")
36
+ raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, "Google Places Details API error: invalid request.")
37
37
  end
38
38
 
39
39
  []
@@ -0,0 +1,33 @@
1
+ require "geocoder/lookups/google"
2
+ require "geocoder/results/google_places_search"
3
+
4
+ module Geocoder
5
+ module Lookup
6
+ class GooglePlacesSearch < Google
7
+ def name
8
+ "Google Places Search"
9
+ end
10
+
11
+ def required_api_key_parts
12
+ ["key"]
13
+ end
14
+
15
+ def supported_protocols
16
+ [:https]
17
+ end
18
+
19
+ private
20
+
21
+ def base_query_url(query)
22
+ "#{protocol}://maps.googleapis.com/maps/api/place/textsearch/json?"
23
+ end
24
+
25
+ def query_url_google_params(query)
26
+ {
27
+ query: query.text,
28
+ language: query.language || configuration.language
29
+ }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -11,7 +11,7 @@ module Geocoder::Lookup
11
11
  end
12
12
 
13
13
  def required_api_key_parts
14
- ["private key", "client", "channel"]
14
+ ["private key"]
15
15
  end
16
16
 
17
17
  def query_url(query)
@@ -21,6 +21,16 @@ module Geocoder::Lookup
21
21
 
22
22
  private # ---------------------------------------------------------------
23
23
 
24
+ def cache_key(query)
25
+ "#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + hash_to_query(cache_key_params(query))
26
+ end
27
+
28
+ def cache_key_params(query)
29
+ query_url_google_params(query).merge(super).reject do |k,v|
30
+ [:key, :client, :channel].include?(k)
31
+ end
32
+ end
33
+
24
34
  def query_url_params(query)
25
35
  query_url_google_params(query).merge(super).merge(
26
36
  :key => nil, # don't use param inherited from Google lookup
@@ -9,15 +9,19 @@ module Geocoder::Lookup
9
9
  end
10
10
 
11
11
  def required_api_key_parts
12
- []
12
+ ['api_key']
13
13
  end
14
14
 
15
- def query_url(query)
16
- "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.api.here.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?" + url_query_string(query)
15
+ def supported_protocols
16
+ [:https]
17
17
  end
18
18
 
19
19
  private # ---------------------------------------------------------------
20
20
 
21
+ def base_query_url(query)
22
+ "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.ls.hereapi.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
23
+ end
24
+
21
25
  def results(query)
22
26
  return [] unless doc = fetch_data(query)
23
27
  return [] unless doc['Response'] && doc['Response']['View']
@@ -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