135 lines
4.9 KiB
Ruby
135 lines
4.9 KiB
Ruby
require 'csv'
|
|
|
|
module JamRuby
|
|
class MaxMindGeo < ActiveRecord::Base
|
|
|
|
self.table_name = 'max_mind_geo'
|
|
|
|
def self.ip_lookup(ip_addy)
|
|
addr = MaxMindIsp.ip_address_to_int(ip_addy)
|
|
self.where(["ip_start <= ? AND ? <= ip_end", addr, addr])
|
|
.limit(1)
|
|
.first
|
|
end
|
|
|
|
def self.import_from_max_mind(file)
|
|
|
|
# File Geo-139
|
|
# Format:
|
|
# startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode
|
|
|
|
MaxMindGeo.transaction do
|
|
MaxMindGeo.delete_all
|
|
File.open(file, 'r:ISO-8859-1') do |io|
|
|
s = io.gets.strip # eat the headers line
|
|
unless s.eql? 'startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode'
|
|
puts s
|
|
puts 'startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode'
|
|
raise 'file does not start with expected header (line 1): startIpNum,endIpNum,country,region,city,postalCode,latitude,longitude,dmaCode,areaCode'
|
|
end
|
|
|
|
saved_level = ActiveRecord::Base.logger ? ActiveRecord::Base.logger.level : 0
|
|
count = 0
|
|
|
|
stmt = "insert into #{MaxMindGeo.table_name} (country,region,city,lat,lng,ip_start,ip_end) values"
|
|
|
|
vals = ''
|
|
sep = ''
|
|
i = 0
|
|
n = 20 # going from 20 to 40 only changed things a little bit
|
|
|
|
csv = ::CSV.new(io, {encoding: 'ISO-8859-1', headers: false})
|
|
csv.each do |row|
|
|
raise "file does not have expected number of columns (10): #{row.length}" unless row.length == 10
|
|
|
|
ip_start = MaxMindIsp.ip_address_to_int(MaxMindIsp.strip_quotes(row[0]))
|
|
ip_end = MaxMindIsp.ip_address_to_int(MaxMindIsp.strip_quotes(row[1]))
|
|
country = row[2]
|
|
region = row[3]
|
|
city = row[4]
|
|
#postalcode = row[5]
|
|
lat = row[6]
|
|
lng = row[7]
|
|
#dmacode = row[8]
|
|
#areacode = row[9]
|
|
|
|
vals = vals+sep+"(#{quote_value(country)},#{quote_value(region)},#{quote_value(city)},#{lat},#{lng},#{ip_start},#{ip_end})"
|
|
sep = ','
|
|
i += 1
|
|
|
|
if count == 0 or i >= n then
|
|
MaxMindGeo.connection.execute stmt+vals
|
|
count += i
|
|
vals = ''
|
|
sep = ''
|
|
i = 0
|
|
|
|
if ActiveRecord::Base.logger and ActiveRecord::Base.logger.level > 1 then
|
|
ActiveRecord::Base.logger.debug "... logging inserts into #{MaxMindGeo.table_name} suspended ..."
|
|
ActiveRecord::Base.logger.level = 1
|
|
end
|
|
|
|
if ActiveRecord::Base.logger and count%10000 < n then
|
|
ActiveRecord::Base.logger.level = saved_level
|
|
ActiveRecord::Base.logger.debug "... inserted #{count} into #{MaxMindGeo.table_name} ..."
|
|
ActiveRecord::Base.logger.level = 1
|
|
end
|
|
end
|
|
end
|
|
|
|
if i > 0 then
|
|
MaxMindGeo.connection.execute stmt+vals
|
|
count += i
|
|
end
|
|
|
|
if ActiveRecord::Base.logger then
|
|
ActiveRecord::Base.logger.level = saved_level
|
|
ActiveRecord::Base.logger.debug "loaded #{count} records into #{MaxMindGeo.table_name}"
|
|
end
|
|
end
|
|
end
|
|
# User.find_each { |usr| usr.update_lat_lng }
|
|
Band.find_each { |bnd| bnd.update_lat_lng }
|
|
end
|
|
|
|
def self.where_latlng(relation, params, current_user=nil)
|
|
# this is only valid to call when relation is about bands
|
|
distance = params[:distance].to_i
|
|
if distance > 0
|
|
latlng = nil
|
|
location_city = params[:city]
|
|
location_state = params[:state]
|
|
location_country = params[:country]
|
|
remote_ip = params[:remote_ip]
|
|
|
|
if location_city and location_state and location_country
|
|
geo = self.where(city: location_city, region: location_state, country: location_country).limit(1).first
|
|
if geo and geo.lat and geo.lng and (geo.lat != 0 or geo.lng != 0)
|
|
# it isn't reasonable for both to be 0...
|
|
latlng = [geo.lat, geo.lng]
|
|
end
|
|
elsif current_user and current_user.locidispid and current_user.locidispid != 0
|
|
location = GeoIpLocations.lookup(current_user.locidispid/1000000)
|
|
if location and location.latitude and location.longitude and (location.latitude != 0 or location.longitude != 0)
|
|
# it isn't reasonable for both to be 0...
|
|
latlng = [location.latitude, location.longitude]
|
|
end
|
|
elsif remote_ip
|
|
geo = self.ip_lookup(remote_ip)
|
|
if geo and geo.lat and geo.lng and (geo.lat != 0 or geo.lng != 0)
|
|
# it isn't reasonable for both to be 0...
|
|
latlng = [geo.lat, geo.lng]
|
|
end
|
|
end
|
|
|
|
if latlng
|
|
relation = relation.where(['lat IS NOT NULL AND lng IS NOT NULL']).within(distance, origin: latlng)
|
|
end
|
|
end
|
|
relation
|
|
end
|
|
|
|
end
|
|
|
|
end
|