require 'resolv' require 'jdx/geocoder/version' require 'jdx/geocoder/base' require 'jdx/geocoder/request' require 'jdx/geocoder/google' require 'jdx/geocoder/ip_api' module JDX module Geocoder STATE_ABB = { 'al' => 'alabama', 'ak' => 'alaska', 'as' => 'america samoa', 'az' => 'arizona', 'ar' => 'arkansas', 'ca' => 'california', 'co' => 'colorado', 'ct' => 'connecticut', 'de' => 'delaware', 'dc' => 'district of columbia', 'fm' => 'federated states of micronesia', 'fl' => 'florida', 'ga' => 'georgia', 'gu' => 'guam', 'hi' => 'hawaii', 'id' => 'idaho', 'il' => 'illinois', 'in' => 'indiana', 'ia' => 'iowa', 'ks' => 'kansas', 'ky' => 'kentucky', 'la' => 'louisiana', 'me' => 'maine', 'mh' => 'marshall islands', 'md' => 'maryland', 'ma' => 'massachusetts', 'mi' => 'michigan', 'mn' => 'minnesota', 'ms' => 'mississippi', 'mo' => 'missouri', 'mt' => 'montana', 'ne' => 'nebraska', 'nv' => 'nevada', 'nh' => 'new hampshire', 'nj' => 'new jersey', 'nm' => 'new mexico', 'ny' => 'new york', 'nc' => 'north carolina', 'nd' => 'north dakota', 'oh' => 'ohio', 'ok' => 'oklahoma', 'or' => 'oregon', 'pw' => 'palau', 'pa' => 'pennsylvania', 'pr' => 'puerto rico', 'ri' => 'rhode island', 'sc' => 'south carolina', 'sd' => 'south dakota', 'tn' => 'tennessee', 'tx' => 'texas', 'ut' => 'utah', 'vt' => 'vermont', 'vi' => 'virgin island', 'va' => 'virginia', 'wa' => 'washington', 'wv' => 'west virginia', 'wi' => 'wisconsin', 'wy' => 'wyoming' }.freeze STATE_ABB_REGEXP = Regexp.new(STATE_ABB.keys.map { |x| "\\b#{x}\\b" }.join('|')).freeze class << self attr_accessor :configuration def configure self.configuration ||= Configuration.new yield(configuration) end def location_search(term, sanitize: true) return if term.nil? term = sanitize(term) if sanitize return if term.empty? ::JDX::Geocoder::Google.new(term).search end def ip_search(ip, validate: false) return nil if ip.nil? || ip.empty? || validate && !valid_ip?(ip) ::JDX::Geocoder::IpApi.new(ip).search end def sanitize(term) down = term.downcase return 'us' if countrywide?(down) zip = extract_zipcode(down) return zip unless zip.nil? remove_stuff(down) remove_duplicates(down) end def countrywide?(down) down.match?(/\b(nation?.|country?.)wide\b/) end def extract_zipcode(down) down.match(/\b[0-9]{5}(?:-[0-9]{4})?\b/)&.[](0) end def remove_stuff(down) down.gsub!(%r{\b(?:united\W*st?ates(?:\W*of\W*america)?|u\W*s\W*a?|n/a)\b}, '') down.gsub!(STATE_ABB_REGEXP, STATE_ABB) end def remove_duplicates(down) down.split(/\W+/).tap(&:uniq!).join(' ').tap(&:strip!) end def valid_ip?(ip) case ip when Resolv::IPv4::Regex, Resolv::IPv6::Regex true else false end end end class Configuration attr_accessor :ipapi_key, :google_key, :location_cache_db, :ip_cache_db, :error_handler end end end