]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/core/irclog.rb
0c024ddd72a01a5b3d371d074c5317974f8c4704
[user/henk/code/ruby/rbot.git] / lib / rbot / core / irclog.rb
1 #-- vim:sw=2:et
2 #++
3 #
4 # :title: rbot IRC logging facilities
5 #
6 # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
7 # Copyright:: (C) 2008 Giuseppe Bilotta
8 # License:: GPL v2
9
10 class IrcLogModule < CoreBotModule
11
12   MAX_OPEN_FILES = 20 # XXX: maybe add a config value
13   
14   def initialize
15     super
16     @logs = Hash.new
17     Dir.mkdir("#{@bot.botclass}/logs") unless File.exist?("#{@bot.botclass}/logs")
18   end
19
20   def logfile_close(where_str, reason = 'unknown reason')
21     f = @logs.delete(where_str) or return
22     stamp = Time.now.strftime '%Y/%m/%d %H:%M:%S'
23     f[1].puts "[#{stamp}] @ Log closed by #{@bot.myself.nick} (#{reason})"
24     f[1].close
25   end
26
27   # log IRC-related message +message+ to a file determined by +where+.
28   # +where+ can be a channel name, or a nick for private message logging
29   def irclog(message, where="server")
30     message = message.chomp
31     now = Time.now
32     stamp = now.strftime("%Y/%m/%d %H:%M:%S")
33     if where.class <= Server
34       where_str = "server"
35     else
36       where_str = where.downcase.gsub(/[:!?$*()\/\\<>|"']/, "_")
37     end
38     unless @logs.has_key? where_str
39       if @logs.size > MAX_OPEN_FILES
40         @logs.keys.sort do |a, b|
41           @logs[a][0] <=> @logs[b][0]
42         end.slice(0, @logs.size - MAX_OPEN_FILES).each do |w|
43           logfile_close w, "idle since #{@logs[w][0]}"
44         end
45       end
46       f = File.new("#{@bot.botclass}/logs/#{where_str}", "a")
47       f.sync = true
48       f.puts "[#{stamp}] @ Log started by #{@bot.myself.nick}"
49       @logs[where_str] = [now, f]
50     end
51     @logs[where_str][1].puts "[#{stamp}] #{message}"
52     @logs[where_str][0] = now
53     #debug "[#{stamp}] <#{where}> #{message}"
54   end
55
56   def sent(m)
57     case m
58     when NoticeMessage
59       irclog "-#{m.source}- #{m.message}", m.target
60     when PrivMessage
61       irclog "<#{m.source}> #{m.message}", m.target
62     when QuitMessage
63       m.was_on.each { |ch|
64         irclog "@ quit (#{m.message})", ch
65       }
66     end
67   end
68
69   def welcome(m)
70     irclog "joined server #{m.server} as #{m.target}", "server"
71   end
72
73   def listen(m)
74     case m
75     when PrivMessage
76       method = 'log_message'
77     else
78       method = 'log_' + m.class.name.downcase.match(/^irc::(\w+)message$/).captures.first
79     end
80     if self.respond_to?(method)
81       self.__send__(method, m)
82     else
83       warning "unhandled logging for #{m.pretty_inspect} (no such method #{method})"
84       unknown_message(m)
85     end
86   end
87
88   def log_message(m)
89     if m.ctcp
90       who = m.private? ? "me" : m.target
91       logtarget = m.private? ? m.source : m.target
92       case m.ctcp.intern
93       when :ACTION
94         if m.public?
95           irclog "* #{m.source} #{m.logmessage}", m.target
96         else
97           irclog "* #{m.source}(#{m.sourceaddress}) #{m.logmessage}", m.source
98         end
99       when :VERSION
100         irclog "@ #{m.source} asked #{who} about version info", logtarget
101       when :SOURCE
102         irclog "@ #{m.source} asked #{who} about source info", logtarget
103       when :PING
104         irclog "@ #{m.source} pinged #{who}", logtarget
105       when :TIME
106         irclog "@ #{m.source} asked #{who} what time it is", logtarget
107       else
108         irclog "@ #{m.source} asked #{who} about #{[m.ctcp, m.message].join(' ')}", logtarget
109       end
110     else
111       if m.public? 
112         irclog "<#{m.source}> #{m.logmessage}", m.target
113       else
114         irclog "<#{m.source}(#{m.sourceaddress})> #{m.logmessage}", m.source
115       end
116     end
117   end
118
119   def log_notice(m)
120     if m.private?
121       irclog "-#{m.source}(#{m.sourceaddress})- #{m.logmessage}", m.source
122     else
123       irclog "-#{m.source}- #{m.logmessage}", m.target
124     end
125   end
126
127   def motd(m)
128     m.message.each_line { |line|
129       irclog "MOTD: #{line}", "server"
130     }
131   end
132
133   def log_nick(m)
134     m.is_on.each { |ch|
135       irclog "@ #{m.oldnick} is now known as #{m.newnick}", ch
136     }
137   end
138
139   def log_quit(m)
140     m.was_on.each { |ch|
141       irclog "@ Quit: #{m.source}: #{m.logmessage}", ch
142     }
143   end
144
145   def modechange(m)
146     irclog "@ Mode #{m.logmessage} by #{m.source}", m.target
147   end
148
149   def log_join(m)
150     if m.address?
151       debug "joined channel #{m.channel}"
152       irclog "@ Joined channel #{m.channel}", m.channel
153     else
154       irclog "@ #{m.source} joined channel #{m.channel}", m.channel
155     end
156   end
157
158   def log_part(m)
159     if(m.address?)
160       debug "left channel #{m.channel}"
161       irclog "@ Left channel #{m.channel} (#{m.logmessage})", m.channel
162     else
163       irclog "@ #{m.source} left channel #{m.channel} (#{m.logmessage})", m.channel
164     end
165   end
166
167   def log_kick(m)
168     if(m.address?)
169       debug "kicked from channel #{m.channel}"
170       irclog "@ You have been kicked from #{m.channel} by #{m.source} (#{m.logmessage})", m.channel
171     else
172       irclog "@ #{m.target} has been kicked from #{m.channel} by #{m.source} (#{m.logmessage})", m.channel
173     end
174   end
175
176   # def log_invite(m)
177   #   # TODO
178   # end
179
180   def log_topic(m)
181     case m.info_or_set
182     when :set
183       if m.source == @bot.myself
184         irclog "@ I set topic \"#{m.topic}\"", m.channel
185       else
186         irclog "@ #{m.source} set topic \"#{m.topic}\"", m.channel
187       end
188     when :info
189       topic = m.channel.topic
190       irclog "@ Topic is \"#{m.topic}\"", m.channel
191       irclog "@ Topic set by #{topic.set_by} on #{topic.set_on}", m.channel
192     end
193   end
194
195   # def names(m)
196   #   # TODO
197   # end
198
199   def unknown_message(m)
200     irclog m.logmessage, ".unknown"
201   end
202 end
203
204 ilm = IrcLogModule.new
205 ilm.priority = -1
206