From 0b7a1abfdc4d42237f9dfa751c9f5bca71c5e190 Mon Sep 17 00:00:00 2001 From: Robert Schaefer <robert.schaefer@student.hpi.de> Date: Mon, 8 Jan 2018 03:08:50 +0100 Subject: [PATCH] Provide ipdata.co as a lookup --- lib/geocoder/lookup.rb | 1 + lib/geocoder/lookups/ipdata_co.rb | 51 +++++++++++++++++++++++++++ lib/geocoder/results/ipdata_co.rb | 45 +++++++++++++++++++++++ test/fixtures/ipdata_co_74_200_247_59 | 24 +++++++++++++ test/fixtures/ipdata_co_no_results | 1 + test/test_helper.rb | 8 +++++ test/unit/error_handling_test.rb | 4 +-- test/unit/lookup_test.rb | 2 +- test/unit/lookups/ipdata_co_test.rb | 19 ++++++++++ 9 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 lib/geocoder/lookups/ipdata_co.rb create mode 100644 lib/geocoder/results/ipdata_co.rb create mode 100644 test/fixtures/ipdata_co_74_200_247_59 create mode 100644 test/fixtures/ipdata_co_no_results create mode 100644 test/unit/lookups/ipdata_co_test.rb diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index 2d710419..b756f768 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -71,6 +71,7 @@ module Geocoder :maxmind_geoip2, :ipinfo_io, :ipapi_com, + :ipdata_co, :db_ip_com ] end diff --git a/lib/geocoder/lookups/ipdata_co.rb b/lib/geocoder/lookups/ipdata_co.rb new file mode 100644 index 00000000..f1322a2c --- /dev/null +++ b/lib/geocoder/lookups/ipdata_co.rb @@ -0,0 +1,51 @@ +require 'geocoder/lookups/base' +require 'geocoder/results/ipdata_co' + +module Geocoder::Lookup + class IpdataCo < Base + + def name + "ipdata.co" + end + + def supported_protocols + [:https] + end + + def query_url(query) + "#{protocol}://#{host}/#{query.sanitized_text}" + end + + private # --------------------------------------------------------------- + + def parse_raw_data(raw_data) + raw_data.match(/^<html><title>404/) ? nil : super(raw_data) + end + + def results(query) + # don't look up a loopback address, just return the stored result + return [reserved_result(query.text)] if query.loopback_ip_address? + # note: Ipdata.co returns plain text on bad request + (doc = fetch_data(query)) ? [doc] : [] + end + + def reserved_result(ip) + { + "ip" => ip, + "city" => "", + "region_code" => "", + "region_name" => "", + "metrocode" => "", + "zipcode" => "", + "latitude" => "0", + "longitude" => "0", + "country_name" => "Reserved", + "country_code" => "RD" + } + end + + def host + "api.ipdata.co" + end + end +end diff --git a/lib/geocoder/results/ipdata_co.rb b/lib/geocoder/results/ipdata_co.rb new file mode 100644 index 00000000..497ac156 --- /dev/null +++ b/lib/geocoder/results/ipdata_co.rb @@ -0,0 +1,45 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class IpdataCo < Base + + def address(format = :full) + s = state_code.to_s == "" ? "" : ", #{state_code}" + "#{city}#{s} #{postal_code}, #{country}".sub(/^[ ,]*/, "") + end + + def city + @data['city'] + end + + def state + @data['region'] + end + + def state_code + @data['region_code'] + end + + def country + @data['country_name'] + end + + def country_code + @data['country_code'] + end + + def postal_code + @data['postal'] + end + + def self.response_attributes + %w[ip asn organisation currency currency_symbol calling_code flag time_zone is_eu] + end + + response_attributes.each do |a| + define_method a do + @data[a] + end + end + end +end diff --git a/test/fixtures/ipdata_co_74_200_247_59 b/test/fixtures/ipdata_co_74_200_247_59 new file mode 100644 index 00000000..a2da12b5 --- /dev/null +++ b/test/fixtures/ipdata_co_74_200_247_59 @@ -0,0 +1,24 @@ +{ + "ip": "74.200.247.59", + "city": "Jersey City", + "region": "New Jersey", + "region_code": "NJ", + "country_name": "United States", + "country_code": "US", + "continent_name": "North America", + "continent_code": "NA", + "latitude": 40.7209, + "longitude": -74.0468, + "asn": "AS22576", + "organisation": "DataPipe, Inc.", + "postal": "07302", + "currency": "USD", + "currency_symbol": "$", + "calling_code": "1", + "flag": "https://ipdata.co/flags/us.png", + "time_zone": "America/New_York", + "is_eu": false, + "suspicious_factors": { + "is_tor": false + } +} \ No newline at end of file diff --git a/test/fixtures/ipdata_co_no_results b/test/fixtures/ipdata_co_no_results new file mode 100644 index 00000000..896eaf56 --- /dev/null +++ b/test/fixtures/ipdata_co_no_results @@ -0,0 +1 @@ +0.0.0 does not appear to be an IPv4 or IPv6 address \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 87e11da4..4857dfed 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -373,6 +373,14 @@ module Geocoder end end + require 'geocoder/lookups/ipdata_co' + class IpdataCo + private + def default_fixture_filename + "ipdata_co_74_200_247_59" + end + end + require 'geocoder/lookups/ban_data_gouv_fr' class BanDataGouvFr private diff --git a/test/unit/error_handling_test.rb b/test/unit/error_handling_test.rb index ca20f3e5..689d1fe5 100644 --- a/test/unit/error_handling_test.rb +++ b/test/unit/error_handling_test.rb @@ -19,7 +19,7 @@ class ErrorHandlingTest < GeocoderTestCase def test_always_raise_response_parse_error Geocoder.configure(:always_raise => [Geocoder::ResponseParseError]) - [:freegeoip, :google, :okf].each do |l| + [:freegeoip, :google, :ipdata_co, :okf].each do |l| lookup = Geocoder::Lookup.get(l) set_api_key!(l) assert_raises Geocoder::ResponseParseError do @@ -29,7 +29,7 @@ class ErrorHandlingTest < GeocoderTestCase end def test_never_raise_response_parse_error - [:freegeoip, :google, :okf].each do |l| + [:freegeoip, :google, :ipdata_co, :okf].each do |l| lookup = Geocoder::Lookup.get(l) set_api_key!(l) silence_warnings do diff --git a/test/unit/lookup_test.rb b/test/unit/lookup_test.rb index 8dcaf804..7f21877f 100644 --- a/test/unit/lookup_test.rb +++ b/test/unit/lookup_test.rb @@ -24,7 +24,7 @@ class LookupTest < GeocoderTestCase def test_query_url_contains_values_in_params_hash Geocoder::Lookup.all_services_except_test.each do |l| - next if [:freegeoip, :maxmind_local, :telize, :pointpin, :geoip2, :maxmind_geoip2, :mapbox, :ipinfo_io, :ipapi_com].include? l # does not use query string + next if [:freegeoip, :maxmind_local, :telize, :pointpin, :geoip2, :maxmind_geoip2, :mapbox, :ipdata_co, :ipinfo_io, :ipapi_com].include? l # does not use query string set_api_key!(l) url = Geocoder::Lookup.get(l).query_url(Geocoder::Query.new( "test", :params => {:one_in_the_hand => "two in the bush"} diff --git a/test/unit/lookups/ipdata_co_test.rb b/test/unit/lookups/ipdata_co_test.rb new file mode 100644 index 00000000..fcd98f80 --- /dev/null +++ b/test/unit/lookups/ipdata_co_test.rb @@ -0,0 +1,19 @@ +# encoding: utf-8 +require 'test_helper' + +class IpdataCoTest < GeocoderTestCase + + def setup + Geocoder.configure(ip_lookup: :ipdata_co) + end + + def test_result_on_ip_address_search + result = Geocoder.search("74.200.247.59").first + assert result.is_a?(Geocoder::Result::IpdataCo) + end + + def test_result_components + result = Geocoder.search("74.200.247.59").first + assert_equal "Jersey City, NJ 07302, United States", result.address + end +end -- GitLab