lib/ipinfo.rb in IPinfo-1.0.1 vs lib/ipinfo.rb in IPinfo-1.1.0
- old
+ new
@@ -6,19 +6,32 @@
require 'ipinfo/cache/default_cache'
require 'ipinfo/errors'
require 'ipinfo/response'
require 'ipinfo/version'
require 'json'
+require_relative 'ipinfo/ipAddressMatcher'
module IPinfo
DEFAULT_CACHE_MAXSIZE = 4096
DEFAULT_CACHE_TTL = 60 * 60 * 24
DEFAULT_COUNTRY_FILE = File.join(File.dirname(__FILE__),
'ipinfo/countries.json')
+ DEFAULT_EU_COUNTRIES_FILE = File.join(File.dirname(__FILE__),
+ 'ipinfo/eu.json')
+ DEFAULT_COUNTRIES_FLAG_FILE = File.join(File.dirname(__FILE__),
+ 'ipinfo/flags.json')
+ DEFAULT_COUNTRIES_CURRENCIES_FILE = File.join(File.dirname(__FILE__),
+ 'ipinfo/currency.json')
+ DEFAULT_CONTINENT_FILE = File.join(File.dirname(__FILE__),
+ 'ipinfo/continent.json')
RATE_LIMIT_MESSAGE = 'To increase your limits, please review our ' \
'paid plans at https://ipinfo.io/pricing'
+ # Base URL to get country flag image link.
+ # "PK" -> "https://cdn.ipinfo.io/static/images/countries-flags/PK.svg"
+ COUNTRY_FLAGS_URL = "https://cdn.ipinfo.io/static/images/countries-flags/"
+
class << self
def create(access_token = nil, settings = {})
IPinfo.new(access_token, settings)
end
end
@@ -33,19 +46,36 @@
@httpc = prepare_http_client(settings.fetch('http_client', nil))
maxsize = settings.fetch('maxsize', DEFAULT_CACHE_MAXSIZE)
ttl = settings.fetch('ttl', DEFAULT_CACHE_TTL)
@cache = settings.fetch('cache', DefaultCache.new(ttl, maxsize))
- @countries = prepare_countries(settings.fetch('countries',
+ @countries = prepare_json(settings.fetch('countries',
DEFAULT_COUNTRY_FILE))
+ @eu_countries = prepare_json(settings.fetch('eu_countries',
+ DEFAULT_EU_COUNTRIES_FILE))
+ @countries_flags = prepare_json(settings.fetch('countries_flags',
+ DEFAULT_COUNTRIES_FLAG_FILE))
+ @countries_currencies = prepare_json(settings.fetch('countries_currencies',
+ DEFAULT_COUNTRIES_CURRENCIES_FILE))
+ @continents = prepare_json(settings.fetch('continents',
+ DEFAULT_CONTINENT_FILE))
end
def details(ip_address = nil)
details = request_details(ip_address)
if details.key? :country
details[:country_name] =
@countries.fetch(details.fetch(:country), nil)
+ details[:is_eu] =
+ @eu_countries.include?(details.fetch(:country))
+ details[:country_flag] =
+ @countries_flags.fetch(details.fetch(:country), nil)
+ details[:country_currency] =
+ @countries_currencies.fetch(details.fetch(:country), nil)
+ details[:continent] =
+ @continents.fetch(details.fetch(:country), nil)
+ details[:country_flag_url] = COUNTRY_FLAGS_URL + details.fetch(:country) + ".svg"
end
if details.key? :ip
details[:ip_address] =
IPAddr.new(details.fetch(:ip))
@@ -58,25 +88,88 @@
end
Response.new(details)
end
+ def get_map_url(ips)
+ if !ips.kind_of?(Array)
+ return JSON.generate({:error => 'Invalid input. Array required!'})
+ end
+ if ips.length > 500000
+ return JSON.generate({:error => 'No more than 500,000 ips allowed!'})
+ end
+
+ json_ips = JSON.generate({:ips => ips})
+ res = @httpc.post('/tools/map', json_ips)
+
+ obj = JSON.parse(res.body)
+ obj['reportUrl']
+ end
+
+ def batch_requests(url_array, api_token)
+ result = Hash.new
+ lookup_ips = []
+
+ url_array.each { |url|
+ ip = @cache.get(cache_key(url))
+
+ unless ip.nil?
+ result.store(url, ip)
+ else
+ lookup_ips << url
+ end
+ }
+
+ if lookup_ips.empty?
+ return result
+ end
+
+ begin
+ lookup_ips.each_slice(1000){ |ips|
+ json_arr = JSON.generate(lookup_ips)
+ res = @httpc.post("/batch?token=#{api_token}", json_arr, 5)
+
+ raise StandardError, "Request Quota Exceeded" if res.status == 429
+
+ data = JSON.parse(res.body)
+ data.each { |key, val|
+ @cache.set(cache_key(key), val)
+ }
+
+ result.merge!(data)
+ }
+
+ rescue StandardError => e
+ return e.message
+ end
+
+ result
+ end
+
protected
def request_details(ip_address = nil)
- res = @cache.get(ip_address)
+ if isBogon(ip_address)
+ details[:ip] = ip_address
+ details[:bogon] = true
+ details[:ip_address] = IPAddr.new(ip_address)
+
+ return details
+ end
+
+ res = @cache.get(cache_key(ip_address))
return res unless res.nil?
response = @httpc.get(escape_path(ip_address))
if response.status.eql?(429)
raise RateLimitError,
RATE_LIMIT_MESSAGE
end
details = JSON.parse(response.body, symbolize_names: true)
- @cache.set(ip_address, details)
+ @cache.set(cache_key(ip_address), details)
details
end
def prepare_http_client(httpc = nil)
@httpc = if httpc
@@ -84,16 +177,29 @@
else
Adapter.new(access_token)
end
end
- def prepare_countries(filename)
+ def prepare_json(filename)
file = File.read(filename)
JSON.parse(file)
end
private
+ def isBogon(ip)
+ if ip.nil?
+ return false
+ end
+
+ matcher_object = IpAddressMatcher.new(ip)
+ matcher_object.matches
+ end
+
def escape_path(ip)
ip ? "/#{CGI.escape(ip)}" : '/'
+ end
+
+ def cache_key(ip)
+ "1:#{ip}"
end
end