4 # :title: Geo IP Plugin
6 # Author:: Raine Virta <rane@kapsi.fi>
7 # Copyright:: (C) 2008 Raine Virta
10 # Resolves the geographic locations of users (network-wide) and IP addresses
13 GEO_IP = "http://www.geoiptool.com/en/?IP="
15 :country => %r{Country:.*?<a href=".*?" target="_blank"> (.*?)</a>}m,
16 :region => %r{Region:.*?<a href=".*?" target="_blank">(.*?)</a>}m,
17 :city => %r{City:.*?<td align="left" class="arial_bold">(.*?)</td>}m
20 def self.resolve(hostname)
22 raw = Irc::Utils.bot.httputil.get_response(GEO_IP+hostname)
23 raw = raw.decompress_body(raw.raw_body)
25 REGEX.each { |key, regex| res[key] = Iconv.conv('utf-8', 'ISO-8859-1', raw.scan(regex).to_s) }
37 @hash[nick] = [] unless @hash[nick]
50 class GeoIpPlugin < Plugin
51 def help(plugin, topic="")
52 "geoip [<user|hostname|ip>] => returns the geographic location of whichever has been given -- note: user can be anyone on the network"
62 nick = m.whois[:nick].downcase
64 # need to see if the whois reply was invoked by this plugin
65 return unless @stack.has_nick?(nick)
67 @stack[nick].each do |source|
69 @bot.say source, host2output(m.target.host, m.target.nick)
71 @bot.say source, "no such user on "+@bot.server.hostname.split(".")[-2]
75 @stack.clear(m.whois[:nick])
80 m.reply host2output(m.source.host, m.source.nick)
82 if m.replyto.class == Channel
84 # check if there is an user on the channel with nick same as input given
85 user = m.replyto.users.find { |user| user.nick == params[:input] }
88 m.reply host2output(user.host, user.nick)
93 # input is a host name or an IP
94 if params[:input] =~ /[a-z0-9\-]+(?:\.[a-z0-9\-]+)*\.[a-z]{2,4}/i ||
95 params[:input] =~ Resolv::IPv4::Regex
96 m.reply host2output(params[:input])
98 # assume input is a nick
100 nick = params[:input].downcase
102 @stack[nick] << m.replyto
108 def host2output(host, nick=nil)
109 geo = GeoIP::resolve(host)
111 if geo[:country].empty?
112 return _("#{nick ? "#{nick}'s location" : host} could not be resolved")
115 res = _("%{thing} is #{nick ? "from" : "located in"}") % {
116 :thing => (nick ? nick : Resolv::getaddress(host)),
117 :country => geo[:country]
120 res << " %{city}," % {
122 } unless geo[:city].empty?
124 res << " %{country}" % {
125 :country => geo[:country]
128 res << " (%{region})" % {
129 :region => geo[:region]
130 } unless geo[:region].empty? || geo[:region] == geo[:city]
136 plugin = GeoIpPlugin.new
137 plugin.map "geoip [:input]", :action => 'geoip'