]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/geoip.rb
geoip plugin: added nick based network-wide lookup and fixed some charset issues
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / geoip.rb
1 #-- vim:sw=2:et
2 #++
3 #
4 # :title: Geo IP Plugin
5 #
6 # Author:: Raine Virta <rane@kapsi.fi>
7 # Copyright:: (C) 2008 Raine Virta
8 # License:: GPL v2
9 #
10 # Resolves the geographic locations of users (network-wide) and IP addresses
11
12 module GeoIP
13   GEO_IP = "http://www.geoiptool.com/en/?IP="
14   REGEX  = {
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
18   }
19
20
21   def self.resolve(hostname)
22     res = {}
23     raw = Irc::Utils.bot.httputil.get_response(GEO_IP+hostname)
24     raw = raw.decompress_body(raw.raw_body)
25
26     REGEX.each { |key, regex| res[key] = Iconv.conv('utf-8', 'ISO-8859-1', raw.scan(regex).to_s) }
27
28     return res
29   end
30 end
31
32 class GeoIpPlugin < Plugin
33   def help(plugin, topic="")
34     "geoip [<user|hostname|ip>] => returns the geographic location of whichever has been given -- note: user can be anyone on the network"
35   end
36
37   def whois(m)
38     # need to see if the whois reply was invoked by this plugin
39     return unless m.whois[:nick] == @nick
40
41     if m.target
42       @bot.say @source, host2output(m.target.host, m.target.nick)
43     else
44       @bot.say @source, "no such user on "+@bot.server.hostname.split(".")[-2]
45     end
46
47     @nick, @source = nil
48   end
49
50   def geoip(m, params)
51     if params.empty?
52       m.reply host2output(m.source.host, m.source.nick)
53     else
54       if m.replyto.class == Channel
55
56         # check if there is an user on the channel with nick same as input given
57         user = m.replyto.users.find { |user| user.nick == params[:input] }
58
59         if user
60           m.reply host2output(user.host, user.nick)
61           return
62         end
63       end
64
65       # input is a host name or an IP
66       if params[:input] =~ /[a-z0-9\-]+(?:\.[a-z0-9\-]+)*\.[a-z]{2,3}/i ||
67          params[:input] =~ Resolv::IPv4::Regex
68         m.reply host2output(params[:input])
69
70       # assume input is a nick
71       else
72         @source = m.replyto
73         @nick   = params[:input]
74
75         @bot.whois(@nick)
76       end
77     end
78   end
79
80   def host2output(host, nick=nil)
81     geo = GeoIP::resolve(host)
82
83     if geo[:country].empty?
84       return _("#{nick ? "#{nick}'s location" : host} could not be resolved")
85     end
86
87     res = _("%{thing} is #{nick ? "from" : "located in"}") % {
88       :thing   => (nick ? nick : Resolv::getaddress(host)),
89       :country => geo[:country]
90     }
91
92     res << " %{city}," % {
93       :city => geo[:city]
94     } unless geo[:city].empty?
95
96     res << " %{country}" % {
97       :country => geo[:country]
98     }
99
100     res << " (%{region})" % {
101       :region  => geo[:region]
102     } unless geo[:region].empty? || geo[:region] == geo[:city]
103
104     return res
105   end
106 end
107
108 plugin = GeoIpPlugin.new
109 plugin.map "geoip [:input]", :action => 'geoip'