class IrcLogModule
- Author
-
Giuseppe “Oblomov” Bilotta <giuseppe.bilotta@gmail.com>
Attributes
nolog_rx[RW]
Public Class Methods
new()
click to toggle source
Calls superclass method
# File lib/rbot/core/irclog.rb, line 31 def initialize super @queue = Queue.new @thread = Thread.new { loggers_thread } @logs = Hash.new logdir = @bot.path 'logs' Dir.mkdir(logdir) unless File.exist?(logdir) # TODO what shall we do if the logdir couldn't be created? (e.g. it existed as a file) event_irclog_list_changed(@bot.config['irclog.no_log'], @bot.config['irclog.do_log']) @fn_format = @bot.config['irclog.filename_format'] end
Public Instance Methods
can_log_on(where)
click to toggle source
# File lib/rbot/core/irclog.rb, line 43 def can_log_on(where) return true if @dolog_rx and where.match @dolog_rx return false if @nolog_rx and where.match @nolog_rx return true end
cleanup()
click to toggle source
# File lib/rbot/core/irclog.rb, line 77 def cleanup @queue << nil @thread.join @thread = nil end
event_irclog_list_changed(nolist, dolist)
click to toggle source
# File lib/rbot/core/irclog.rb, line 53 def event_irclog_list_changed(nolist, dolist) @nolog_rx = nolist.empty? ? nil : Regexp.union(*(nolist.map { |r| r.to_irc_regexp })) debug "no log: #{@nolog_rx}" @dolog_rx = dolist.empty? ? nil : Regexp.union(*(dolist.map { |r| r.to_irc_regexp })) debug "do log: #{@dolog_rx}" @logs.inject([]) { |ar, kv| ar << kv.first unless can_log_on(kv.first) ar }.each { |w| logfile_close(w, 'logging disabled here') } end
irclog(message, where="server")
click to toggle source
log IRC-related message message
to a file determined by where
. where
can be a channel name, or a nick for private message logging
# File lib/rbot/core/irclog.rb, line 73 def irclog(message, where="server") @queue.push [message, where] end
listen(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 118 def listen(m) case m when PrivMessage method = 'log_message' else method = 'log_' + m.class.name.downcase.match(/^irc::(\w+)message$/).captures.first end if self.respond_to?(method) self.__send__(method, m) else warning "unhandled logging for #{m.pretty_inspect} (no such method #{method})" unknown_message(m) end end
log_join(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 194 def log_join(m) if m.address? debug "joined channel #{m.channel}" irclog "@ Joined channel #{m.channel}", m.channel else irclog "@ #{m.source} joined channel #{m.channel}", m.channel end end
log_kick(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 212 def log_kick(m) if(m.address?) debug "kicked from channel #{m.channel}" irclog "@ You have been kicked from #{m.channel} by #{m.source} (#{m.logmessage})", m.channel else irclog "@ #{m.target} has been kicked from #{m.channel} by #{m.source} (#{m.logmessage})", m.channel end end
log_message(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 133 def log_message(m) if m.ctcp who = m.private? ? "me" : m.target logtarget = m.private? ? m.source : m.target case m.ctcp.intern when :ACTION if m.public? irclog "* #{m.source} #{m.logmessage}", m.target else irclog "* #{m.source}(#{m.sourceaddress}) #{m.logmessage}", m.source end when :VERSION irclog "@ #{m.source} asked #{who} about version info", logtarget when :SOURCE irclog "@ #{m.source} asked #{who} about source info", logtarget when :PING irclog "@ #{m.source} pinged #{who}", logtarget when :TIME irclog "@ #{m.source} asked #{who} what time it is", logtarget else irclog "@ #{m.source} asked #{who} about #{[m.ctcp, m.message].join(' ')}", logtarget end else if m.public? irclog "<#{m.source}> #{m.logmessage}", m.target else irclog "<#{m.source}(#{m.sourceaddress})> #{m.logmessage}", m.source end end end
log_nick(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 178 def log_nick(m) (m.is_on & @bot.myself.channels).each { |ch| irclog "@ #{m.oldnick} is now known as #{m.newnick}", ch } end
log_notice(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 164 def log_notice(m) if m.private? irclog "-#{m.source}(#{m.sourceaddress})- #{m.logmessage}", m.source else irclog "-#{m.source}- #{m.logmessage}", m.target end end
log_part(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 203 def log_part(m) if(m.address?) debug "left channel #{m.channel}" irclog "@ Left channel #{m.channel} (#{m.logmessage})", m.channel else irclog "@ #{m.source} left channel #{m.channel} (#{m.logmessage})", m.channel end end
log_quit(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 184 def log_quit(m) (m.was_on & @bot.myself.channels).each { |ch| irclog "@ Quit: #{m.source}: #{m.logmessage}", ch } end
log_topic(m)
click to toggle source
def log_invite(m)
# TODO
end
# File lib/rbot/core/irclog.rb, line 225 def log_topic(m) case m.info_or_set when :set if m.source == @bot.myself irclog "@ I set topic \"#{m.topic}\"", m.channel else irclog "@ #{m.source} set topic \"#{m.topic}\"", m.channel end when :info topic = m.channel.topic irclog "@ Topic is \"#{m.topic}\"", m.channel irclog "@ Topic set by #{topic.set_by} on #{topic.set_on}", m.channel end end
logfile_close(where_str, reason = 'unknown reason')
click to toggle source
# File lib/rbot/core/irclog.rb, line 64 def logfile_close(where_str, reason = 'unknown reason') f = @logs.delete(where_str) or return stamp = timestamp(Time.now) f[1].puts "#{stamp} @ Log closed by #{@bot.myself.nick} (#{reason})" f[1].close end
logfilepath(where_str, now)
click to toggle source
# File lib/rbot/core/irclog.rb, line 248 def logfilepath(where_str, now) @bot.path('logs', now.strftime(@fn_format) % { :where => where_str }) end
modechange(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 190 def modechange(m) irclog "@ Mode #{m.logmessage} by #{m.source}", m.target end
motd(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 172 def motd(m) m.message.each_line { |line| irclog "MOTD: #{line}", "server" } end
sent(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 83 def sent(m) case m when NoticeMessage irclog "-#{m.source}- #{m.message}", m.target when PrivMessage logtarget = who = m.target if m.ctcp case m.ctcp.intern when :ACTION irclog "* #{m.source} #{m.logmessage}", logtarget when :VERSION irclog "@ #{m.source} asked #{who} about version info", logtarget when :SOURCE irclog "@ #{m.source} asked #{who} about source info", logtarget when :PING irclog "@ #{m.source} pinged #{who}", logtarget when :TIME irclog "@ #{m.source} asked #{who} what time it is", logtarget else irclog "@ #{m.source} asked #{who} about #{[m.ctcp, m.message].join(' ')}", logtarget end else irclog "<#{m.source}> #{m.logmessage}", logtarget end when QuitMessage m.was_on.each { |ch| irclog "@ quit (#{m.message})", ch } end end
timestamp(time)
click to toggle source
# File lib/rbot/core/irclog.rb, line 49 def timestamp(time) return time.strftime(@bot.config['irclog.timestamp_format']) end
unknown_message(m)
click to toggle source
def names(m)
# TODO
end
# File lib/rbot/core/irclog.rb, line 244 def unknown_message(m) irclog m.logmessage, ".unknown" end
welcome(m)
click to toggle source
# File lib/rbot/core/irclog.rb, line 114 def welcome(m) irclog "joined server #{m.server} as #{m.target}", "server" end
Protected Instance Methods
loggers_thread()
click to toggle source
# File lib/rbot/core/irclog.rb, line 253 def loggers_thread ls = nil debug 'loggers_thread starting' while ls = @queue.pop message, where = ls message = message.chomp now = Time.now stamp = timestamp(now) if where.class <= Server where_str = "server" else where_str = where.downcase.gsub(/[:!?$*()\/\\<>|"']/, "_") end next unless can_log_on(where_str) # close the previous logfile if we're rotating if @logs.has_key? where_str fp = logfilepath(where_str, now) logfile_close(where_str, 'log rotation') if fp != @logs[where_str][1].path end # (re)open the logfile if necessary unless @logs.has_key? where_str if @logs.size > @bot.config['irclog.max_open_files'] @logs.keys.sort do |a, b| @logs[a][0] <=> @logs[b][0] end.slice(0, @logs.size - @bot.config['irclog.max_open_files']).each do |w| logfile_close w, "idle since #{@logs[w][0]}" end end fp = logfilepath(where_str, now) begin dir = File.dirname(fp) # first of all, we check we're not trying to build a directory structure # where one of the components exists already as a file, so we # backtrack along dir until we come across the topmost existing name. # If it's a file, we rename to filename.old.filedate up = dir.dup until File.exist? up up.replace(File.dirname(up)) end unless File.directory? up backup = up.dup backup << ".old." << File.atime(up).strftime('%Y%m%d%H%M%S') debug "#{up} is not a directory! renaming to #{backup}" File.rename(up, backup) end FileUtils.mkdir_p(dir) # conversely, it may happen that fp exists and is a directory, in # which case we rename the directory instead if File.directory? fp backup = fp.dup backup << ".old." << File.atime(fp).strftime('%Y%m%d%H%M%S') debug "#{fp} is not a file! renaming to #{backup}" File.rename(fp, backup) end # it should be fine to create the file now f = File.new(fp, "a") f.sync = true f.puts "#{stamp} @ Log started by #{@bot.myself.nick}" rescue Exception => e error e next end @logs[where_str] = [now, f] end @logs[where_str][1].puts "#{stamp} #{message}" @logs[where_str][0] = now #debug "#{stamp} <#{where}> #{message}" end @logs.keys.each { |w| logfile_close(w, 'rescan or shutdown') } debug 'loggers_thread terminating' end