]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/core/irclog.rb
script plugin: report_error() method
[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 cleanup
57     @logs.keys.each { |w| logfile_close(w, 'rescan or shutdown') }
58   end
59
60   def sent(m)
61     case m
62     when NoticeMessage
63       irclog "-#{m.source}- #{m.message}", m.target
64     when PrivMessage
65       irclog "<#{m.source}> #{m.message}", m.target
66     when QuitMessage
67       m.was_on.each { |ch|
68         irclog "@ quit (#{m.message})", ch
69       }
70     end
71   end
72
73   def welcome(m)
74     irclog "joined server #{m.server} as #{m.target}", "server"
75   end
76
77   def listen(m)
78     case m
79     when PrivMessage
80       method = 'log_message'
81     else
82       method = 'log_' + m.class.name.downcase.match(/^irc::(\w+)message$/).captures.first
83     end
84     if self.respond_to?(method)
85       self.__send__(method, m)
86     else
87       warning "unhandled logging for #{m.pretty_inspect} (no such method #{method})"
88       unknown_message(m)
89     end
90   end
91
92   def log_message(m)
93     if m.ctcp
94       who = m.private? ? "me" : m.target
95       logtarget = m.private? ? m.source : m.target
96       case m.ctcp.intern
97       when :ACTION
98         if m.public?
99           irclog "* #{m.source} #{m.logmessage}", m.target
100         else
101           irclog "* #{m.source}(#{m.sourceaddress}) #{m.logmessage}", m.source
102         end
103       when :VERSION
104         irclog "@ #{m.source} asked #{who} about version info", logtarget
105       when :SOURCE
106         irclog "@ #{m.source} asked #{who} about source info", logtarget
107       when :PING
108         irclog "@ #{m.source} pinged #{who}", logtarget
109       when :TIME
110         irclog "@ #{m.source} asked #{who} what time it is", logtarget
111       else
112         irclog "@ #{m.source} asked #{who} about #{[m.ctcp, m.message].join(' ')}", logtarget
113       end
114     else
115       if m.public? 
116         irclog "<#{m.source}> #{m.logmessage}", m.target
117       else
118         irclog "<#{m.source}(#{m.sourceaddress})> #{m.logmessage}", m.source
119       end
120     end
121   end
122
123   def log_notice(m)
124     if m.private?
125       irclog "-#{m.source}(#{m.sourceaddress})- #{m.logmessage}", m.source
126     else
127       irclog "-#{m.source}- #{m.logmessage}", m.target
128     end
129   end
130
131   def motd(m)
132     m.message.each_line { |line|
133       irclog "MOTD: #{line}", "server"
134     }
135   end
136
137   def log_nick(m)
138     m.is_on.each { |ch|
139       irclog "@ #{m.oldnick} is now known as #{m.newnick}", ch
140     }
141   end
142
143   def log_quit(m)
144     m.was_on.each { |ch|
145       irclog "@ Quit: #{m.source}: #{m.logmessage}", ch
146     }
147   end
148
149   def modechange(m)
150     irclog "@ Mode #{m.logmessage} by #{m.source}", m.target
151   end
152
153   def log_join(m)
154     if m.address?
155       debug "joined channel #{m.channel}"
156       irclog "@ Joined channel #{m.channel}", m.channel
157     else
158       irclog "@ #{m.source} joined channel #{m.channel}", m.channel
159     end
160   end
161
162   def log_part(m)
163     if(m.address?)
164       debug "left channel #{m.channel}"
165       irclog "@ Left channel #{m.channel} (#{m.logmessage})", m.channel
166     else
167       irclog "@ #{m.source} left channel #{m.channel} (#{m.logmessage})", m.channel
168     end
169   end
170
171   def log_kick(m)
172     if(m.address?)
173       debug "kicked from channel #{m.channel}"
174       irclog "@ You have been kicked from #{m.channel} by #{m.source} (#{m.logmessage})", m.channel
175     else
176       irclog "@ #{m.target} has been kicked from #{m.channel} by #{m.source} (#{m.logmessage})", m.channel
177     end
178   end
179
180   # def log_invite(m)
181   #   # TODO
182   # end
183
184   def log_topic(m)
185     case m.info_or_set
186     when :set
187       if m.source == @bot.myself
188         irclog "@ I set topic \"#{m.topic}\"", m.channel
189       else
190         irclog "@ #{m.source} set topic \"#{m.topic}\"", m.channel
191       end
192     when :info
193       topic = m.channel.topic
194       irclog "@ Topic is \"#{m.topic}\"", m.channel
195       irclog "@ Topic set by #{topic.set_by} on #{topic.set_on}", m.channel
196     end
197   end
198
199   # def names(m)
200   #   # TODO
201   # end
202
203   def unknown_message(m)
204     irclog m.logmessage, ".unknown"
205   end
206 end
207
208 ilm = IrcLogModule.new
209 ilm.priority = -1
210