summaryrefslogtreecommitdiff
path: root/logger.py
diff options
context:
space:
mode:
Diffstat (limited to 'logger.py')
-rw-r--r--logger.py864
1 files changed, 542 insertions, 322 deletions
diff --git a/logger.py b/logger.py
index 9df6020..01f2bc1 100644
--- a/logger.py
+++ b/logger.py
@@ -12,80 +12,75 @@ import traceback
import Queue
import ssl
import urllib2
+import irc
+modemapping = dict(
+ Y="ircop", q="owner", a="admin", o="op", h="halfop", v="voice")
-class LogRotate(Thread):
- def __init__(self, logger):
- self.logger = logger
- Thread.__init__(self)
- self.daemon = True
- self.start()
-
- def run(self):
- Y, M, D, h, m, s, w, d, dst = time.localtime()
- nextrotate = int(time.mktime((Y, M, D+1, 0, 0, 0, 0, 0, -1)))
- #print time.time()-nextrotate
- #print time.localtime(), time.localtime(nextrotate)
- while True:
- while nextrotate > time.time(): # May need to do this in a loop in case the following time.sleep command wakes up a second too early.
- time.sleep(max(0.1, min((nextrotate-time.time(), 3600))))
- with self.logger.rotatelock:
- if all([not log or log.closed for log in self.logger.consolelogs.values()+self.logger.channellogs.values()]):
- ### If there are no logs to rotate, we are going to terminate this thread. Logger will spawn another LogRotate thread when needed.
- self.logger.logrotate = None
- break
- now = time.localtime()
- timestamp = reduce(lambda x, y: x+":"+y, [str(t)
- .rjust(2, "0") for t in now[0:6]])
- for IRC in self.logger.labels.keys():
- if IRC.connected:
- with IRC.lock:
- try:
- self.logger.rotateConsoleLog(IRC)
- except:
- with IRC.loglock:
- exc, excmsg, tb = sys.exc_info()
- print >>IRC.log, "%(timestamp)s !!! [LogRotate] Exception in module %(module)s" % vars()
- for tbline in traceback.format_exc().split("\n"):
- print >>IRC.log, "%(timestamp)s !!! [LogRotate] %(tbline)s" % vars()
- IRC.log.flush()
- if IRC.identity:
- for channel in IRC.identity.channels:
- try:
- self.logger.rotateChannelLog(channel)
- except:
- with IRC.loglock:
- exc, excmsg, tb = sys.exc_info()
- print >>IRC.log, "%(timestamp)s !!! [LogRotate] Exception in module %(module)s" % vars()
- for tbline in traceback.format_exc().split("\n"):
- print >>IRC.log, "%(timestamp)s !!! [LogRotate] %(tbline)s" % vars()
- IRC.log.flush()
- nextrotate += 3600*24
-
-class Logger(object):
+class Logger(Thread):
def __init__(self, logroot):
self.logroot = logroot
path = [logroot]
- #print path
+
while not os.path.isdir(path[0]):
split = os.path.split(path[0])
path.insert(1, split[1])
path[0] = split[0]
- #print path
+
while len(path) > 1:
path[0] = os.path.join(*path[:2])
del path[1]
#print path
os.mkdir(path[0])
- #return
- self.consolelogs = {}
- self.channellogs = {}
+
+ self.logs = {}
self.labels = {}
self.rotatelock = Lock()
- self.logrotate = None
- def onModuleAdd(self, IRC, label):
+ Thread.__init__(self)
+ self.daemon = True
+ self.start()
+
+ def run(self):
+ try:
+ Y, M, D, h, m, s, w, d, dst = time.localtime()
+ nextrotate = int(time.mktime((Y, M, D+1, 0, 0, 0, 0, 0, -1)))
+ while True:
+ while nextrotate > time.time(): # May need to do this in a loop in case the following time.sleep command wakes up a second too early.
+ time.sleep(max(0.1, min((nextrotate-time.time(), 3600))))
+ with self.rotatelock:
+ if all([not log or log.closed for log in self.logs.values()]):
+ break
+ Y, M, D, h, m, s, w, d, dst = now = time.localtime()
+ for IRC in self.labels.keys():
+ if IRC.connected:
+ with IRC.lock:
+ try:
+ self.rotateLog(IRC)
+ except:
+ exc, excmsg, tb = sys.exc_info()
+ IRC.logwrite(*["!!! [Logger] Exception in module %(module)s" % vars()]+["!!! [Logger] %s" % tbline for tbline in traceback.format_exc().split("\n")])
+ if IRC.identity:
+ for channel in IRC.identity.channels:
+ try:
+ self.rotateLog(channel)
+ except:
+ exc, excmsg, tb = sys.exc_info()
+ IRC.logwrite(*["!!! [Logger] Exception in module %(module)s" % vars()]+["!!! [Logger] %s" % tbline for tbline in traceback.format_exc().split("\n")])
+ for user in IRC.users:
+ if user in self.logs.keys():
+ try:
+ self.closeLog(user)
+ except:
+ exc, excmsg, tb = sys.exc_info()
+ IRC.logwrite(*["!!! [Logger] Exception in module %(module)s" % vars()]+["!!! [Logger] %s" % tbline for tbline in traceback.format_exc().split("\n")])
+ IRC.logopen(os.path.join(self.logroot, self.labels[IRC], "rawdata-%04d.%02d.%02d.log"%now[:3]))
+ nextrotate = int(time.mktime((Y, M, D+1, 0, 0, 0, 0, 0, -1)))
+ finally:
+ Thread.__init__(self)
+
+ def onAddonAdd(self, IRC, label):
if label in self.labels.values():
raise BaseException("Label already exists")
if IRC in self.labels.keys():
@@ -94,289 +89,514 @@ class Logger(object):
os.mkdir(os.path.join(self.logroot, label))
self.labels[IRC] = label
if IRC.connected:
- self.openConsoleLog(IRC)
+ self.openLog(IRC)
if IRC.identity:
for channel in IRC.identity.channels:
- self.openChannelLog(channel)
+ self.openLog(channel)
+ now = time.localtime()
+ timestamp = reduce(lambda x, y: x+":"+y, [str(t).rjust(2,
+ "0") for t in now[0:6]])
+ IRC.logopen(os.path.join(self.logroot, self.labels[IRC],
+ "rawdata-%04d.%02d.%02d.log"%now[:3]))
- def onModuleRem(self, IRC):
+ def onAddonRem(self, IRC):
if IRC.connected:
- for channel in self.channellogs.keys():
+ for channel in self.logs.keys():
if channel in IRC.channels:
- if not self.channellogs[channel].closed:
- self.closeChannelLog(channel)
- del self.channellogs[channel]
- if not self.consolelogs[IRC].closed:
- self.closeConsoleLog(IRC)
+ if not self.logs[channel].closed:
+ self.closeLog(channel)
+ for user in self.logs.keys():
+ if user in IRC.users:
+ if not self.logs[user].closed:
+ self.closeLog(user)
+ if not self.logs[IRC].closed:
+ self.closeLog(IRC)
del self.labels[IRC]
- del self.consolelogs[IRC]
- def openConsoleLog(self, IRC):
- with self.rotatelock:
- if not self.logrotate or not self.logrotate.isAlive():
- self.logrotate = LogRotate(self)
- now = time.localtime()
- timestamp = reduce(lambda x, y: x+":"+y, [str(t).rjust(2,
- "0") for t in now[0:6]])
- self.consolelogs[IRC] = open(os.path.join(self.logroot, self.labels[
- IRC], "console-%04d.%02d.%02d.log"%now[:3]), "a")
- print >>self.consolelogs[IRC], "%s %s ### Log session started" % (
- timestamp, time.tzname[now[-1]])
- self.consolelogs[IRC].flush()
-
- def closeConsoleLog(self, IRC):
- if IRC in self.consolelogs.keys() and type(self.consolelogs[IRC]) == file and not self.consolelogs[IRC].closed:
- now = time.localtime()
- timestamp = reduce(lambda x, y: x+":"+y, [str(t)
- .rjust(2, "0") for t in now[0:6]])
- print >>self.consolelogs[IRC], "%s %s ### Log session ended" % (
- timestamp, time.tzname[now[-1]])
- self.consolelogs[IRC].close()
-
- def rotateConsoleLog(self, IRC):
- self.closeConsoleLog(IRC)
- self.openConsoleLog(IRC)
-
- def openChannelLog(self, channel):
+ def openLog(self, window):
with self.rotatelock:
- if not self.logrotate or not self.logrotate.isAlive():
- self.logrotate = LogRotate(self)
- self.logrotate.daemon = True
- self.logrotate.start()
+ if not self.isAlive():
+ self.start()
now = time.localtime()
timestamp = reduce(lambda x, y: x+":"+y, [str(t).rjust(2,
"0") for t in now[0:6]])
- label = self.labels[channel.context]
- self.channellogs[channel] = open(os.path.join(self.logroot, label, "channel-%s-%04d.%02d.%02d.log"%((urllib2.quote(channel.name.lower()).replace("/", "%2f"),)+now[:3])), "a")
- print >>self.channellogs[channel], "%s %s ### Log session started" % (
- timestamp, time.tzname[now[-1]])
- self.channellogs[channel].flush()
- if channel.context.identity in channel.users:
- if channel.topic:
- print >>self.channellogs[channel], "%s %s <<< :%s 332 %s %s :%s" % (timestamp, time.tzname[now[-1]], channel.context.serv, channel.context.identity.nick, channel.name, channel.topic)
- if channel.topicsetby and channel.topictime:
- print >>self.channellogs[channel], "%s %s <<< :%s 333 %s %s %s %s" % (timestamp, time.tzname[now[-1]], channel.context.serv, channel.context.identity.nick, channel.name, channel.topicsetby, channel.topictime)
- if channel.users:
- secret = "s" in channel.modes.keys() and channel.modes["s"]
- private = "p" in channel.modes.keys() and channel.modes["p"]
- namesusers = []
- modes, symbols = channel.context.supports["PREFIX"]
- print >>self.channellogs[channel], "%s %s <<< :%s 353 %s %s %s :%s" % (timestamp, time.tzname[now[-1]],
- channel.context.serv,
- channel.context.identity.nick,
- "@" if secret else ("*" if private else "="),
- channel.name,
- " ".join(["".join([symbols[k] if modes[k] in channel.modes.keys() and user in channel.modes[modes[k]] else "" for k in xrange(len(modes))])+user.nick for user in channel.users]))
- if channel.modes:
- modes = channel.modes.keys()
- modestr = "".join([mode for mode in modes if mode not in channel.context.supports["CHANMODES"][0]+channel.context.supports["PREFIX"][0] and channel.modes[mode]])
- params = " ".join([channel.modes[mode] for mode in modes if mode in channel.context.supports["CHANMODES"][1]+channel.context.supports["CHANMODES"][2] and channel.modes[mode]])
- print >>self.channellogs[channel], "%s %s <<< :%s 324 %s %s +%s %s" % (timestamp, time.tzname[now[-1]], channel.context.server, channel.context.identity.nick, channel.name, modestr, params)
- if channel.created:
- print >>self.channellogs[channel], "%s %s <<< :%s 329 %s %s %s" % (timestamp, time.tzname[now[-1]], channel.context.serv, channel.context.identity.nick, channel.name, channel.created)
- self.channellogs[channel].flush()
-
- def closeChannelLog(self, channel):
- if channel in self.channellogs.keys() and type(self.channellogs[channel]) == file and not self.channellogs[channel].closed:
- now = time.localtime()
- timestamp = reduce(lambda x, y: x+":"+y, [str(t)
- .rjust(2, "0") for t in now[0:6]])
- print >>self.channellogs[channel], "%s %s ### Log session ended" % (timestamp, time.tzname[now[-1]])
- self.channellogs[channel].close()
-
- def rotateChannelLog(self, channel):
- self.closeChannelLog(channel)
- self.openChannelLog(channel)
-
- def onRecv(self, IRC, line, data):
- modemapping = dict(Y="ircop", q="owner", a="admin", o="op",
- h="halfop", v="voice")
- now = time.localtime()
- timestamp = reduce(lambda x, y: x+":"+y, [str(t).rjust(2,
- "0") for t in now[0:6]])
- if data is None:
- print >>self.consolelogs[IRC], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.consolelogs[IRC].flush()
- return
- (origin, ident, host, cmd, target, params, extinfo) = data
- if re.match("^\\d+$", cmd):
- cmd = int(cmd)
- if cmd in (324, 329):
- modeparams = params.split()
- channame = modeparams[0]
- channel = IRC.channel(channame)
- if channel in self.channellogs.keys() and not self.channellogs[channel].closed:
- log = self.channellogs[channel]
+ if type(window) == irc.Connection:
+ log = self.logs[window] = open(os.path.join(self.logroot, self.labels[window], "console-%04d.%02d.%02d.log"%now[:3]), "a")
+ print >>log, "%s ### Log file opened" % (irc.timestamp())
+ elif type(window) == irc.Channel:
+ label = self.labels[window.context]
+ log = self.logs[window] = open(os.path.join(self.logroot, label, "channel-%s-%04d.%02d.%02d.log"%((urllib2.quote(window.name.lower()).replace("/", "%2f"),)+now[:3])), "a")
+ print >>log, "%s ### Log file opened" % (irc.timestamp())
+ self.logs[window].flush()
+ if window.context.identity in window.users:
+ if window.topic:
+ print >>log, "%s <<< :%s 332 %s %s :%s" % (irc.timestamp(), window.context.serv, window.context.identity.nick, window.name, window.topic)
+ if window.topicsetby and window.topictime:
+ print >>log, "%s <<< :%s 333 %s %s %s %s" % (irc.timestamp(), window.context.serv, window.context.identity.nick, window.name, window.topicsetby, window.topictime)
+ if window.users:
+ secret = "s" in window.modes.keys() and window.modes["s"]
+ private = "p" in window.modes.keys() and window.modes["p"]
+ namesusers = []
+ modes, symbols = window.context.supports["PREFIX"]
+ print >>log, "%s <<< :%s 353 %s %s %s :%s" % (irc.timestamp(),
+ window.context.serv,
+ window.context.identity.nick,
+ "@" if secret else ("*" if private else "="),
+ window.name,
+ " ".join(["".join([symbols[k] if modes[k] in window.modes.keys() and user in window.modes[modes[k]] else "" for k in xrange(len(modes))])+user.nick for user in window.users]))
+ if window.modes:
+ modes = window.modes.keys()
+ modestr = "".join([mode for mode in modes if mode not in window.context.supports["CHANMODES"][0]+window.context.supports["PREFIX"][0] and window.modes[mode]])
+ params = " ".join([window.modes[mode] for mode in modes if mode in window.context.supports["CHANMODES"][1]+window.context.supports["CHANMODES"][2] and window.modes[mode]])
+ print >>log, "%s <<< :%s 324 %s %s +%s %s" % (irc.timestamp(), window.context.serv, window.context.identity.nick, window.name, modestr, params)
+ if window.created:
+ print >>log, "%s <<< :%s 329 %s %s %s" % (irc.timestamp(), window.context.serv, window.context.identity.nick, window.name, window.created)
+ if type(window) == irc.User:
+ logname = os.path.join(self.logroot, self.labels[window.context], "query-%s-%04d.%02d.%02d.log"%((urllib2.quote(window.nick.lower()).replace("/", "%2f"),)+now[:3]))
+ for (other, log) in self.logs.items():
+ if other == window:
+ continue
+ if log.name == logname:
+ print >>log, "%s ### Log file closed" % (irc.timestamp())
+ del self.logs[other]
+ self.logs[window] = log
+ if window not in self.logs.keys():
+ log = self.logs[window] = open(logname, "a")
else:
- log = self.consolelogs[IRC]
- print >>log, "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- log.flush()
- elif cmd == 332:
- channel = IRC.channel(params)
- if channel in self.channellogs.keys() and not self.channellogs[channel].closed:
- log = self.channellogs[channel]
+ log = self.logs[window]
+ print >>log, "%s ### Log file opened" % (irc.timestamp())
+ log.flush()
+
+ def closeLog(self, window):
+ if window in self.logs.keys() and type(self.logs[window]) == file and not self.logs[window].closed:
+ print >>self.logs[window], "%s ### Log file closed" % (
+ irc.timestamp())
+ self.logs[window].close()
+ if window in self.logs.keys():
+ del self.logs[window]
+
+ def rotateLog(self, window):
+ self.closeLog(window)
+ self.openLog(window)
+
+ def onConnectAttempt(self, IRC):
+ if IRC not in self.logs.keys() or (not self.logs[IRC]) or self.logs[IRC].closed:
+ self.openLog(IRC)
+ ts = irc.timestamp()
+ print >>self.logs[IRC], "%s *** Attempting connection to %s:%s." % (
+ ts, IRC.server, IRC.port)
+
+ def onConnect(self, IRC):
+ if IRC not in self.logs.keys() or (not self.logs[IRC]) or self.logs[IRC].closed:
+ self.openLog(IRC)
+ ts = irc.timestamp()
+ print >>self.logs[IRC], "%s *** Connection to %s:%s established." % (
+ ts, IRC.server, IRC.port)
+
+ def onConnectFail(self, IRC, exc, excmsg, tb):
+ ### Called when a connection attempt fails.
+ if IRC not in self.logs.keys() or (not self.logs[IRC]) or self.logs[IRC].closed:
+ self.openLog(IRC)
+ ts = irc.timestamp()
+ print >>self.logs[IRC], "%s *** Connection to %s:%s failed: %s." % (
+ ts, IRC.server, IRC.port, excmsg)
+
+ def onDisconnect(self, IRC, expected=False):
+ ts = irc.timestamp()
+ for window in self.logs.keys():
+ if type(window) in (irc.Channel, irc.User) and window.context == IRC:
+ print >>self.logs[window], "%s *** Connection to %s:%s terminated." % (ts, IRC.server, IRC.port)
+ self.logs[window].flush()
+ self.closeLog(window)
+ print >>self.logs[IRC], "%s *** Connection %s:%s terminated." % (
+ ts, IRC.server, IRC.port)
+ self.logs[IRC].flush()
+ self.closeLog(IRC)
+
+ def onJoin(self, IRC, user, channel):
+ ### Called when somebody joins a channel, includes bot.
+ ts = irc.timestamp()
+ if user == IRC.identity:
+ self.openLog(channel)
+ print >>self.logs[channel], "%s <<< :%s!%s@%s JOIN %s" % (
+ ts, user.nick, user.username, user.host, channel.name)
+ self.logs[channel].flush()
+
+ def onChanMsg(self, IRC, user, channel, targetprefix, msg):
+ ### Called when someone sends a PRIVMSG to channel.
+ ts = irc.timestamp()
+ if type(user) == irc.User:
+ classes = " ".join([modemapping[mode] for mode in IRC.supports["PREFIX"][0] if mode in channel.modes.keys() and user in channel.modes[mode]])
+ if classes:
+ print >>self.logs[channel], "%s %s <<< :%s!%s@%s PRIVMSG %s%s :%s" % (ts, classes, user.nick, user.username, user.host, targetprefix, channel.name, msg)
else:
- log = self.consolelogs[IRC]
- print >>log, "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- log.flush()
- elif cmd == 333:
- (channame, nick, dt) = params.split()
- channel = IRC.channel(channame)
- if not self.channellogs[channel].closed:
- print >>self.channellogs[channel], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
- elif cmd == 353:
- (flag, channame) = params.split()
- channel = IRC.channel(channame)
- if not self.channellogs[channel].closed:
- print >>self.channellogs[channel], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
- elif cmd == "JOIN":
- user = IRC.user(origin)
- channel = IRC.channel(target if len(target) else extinfo)
- if user == IRC.identity:
- self.openChannelLog(channel)
- print >>self.channellogs[channel], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
- elif cmd == "PRIVMSG":
- if target and target[0] in IRC.supports["CHANTYPES"]:
- channel = IRC.channel(target)
- if ident and host:
- user = IRC.user(origin)
- classes = " ".join([modemapping[mode] for mode in IRC.supports["PREFIX"][0] if mode in channel.modes.keys() and user in channel.modes[mode]])
- else:
- classes = "server"
- if classes:
- print >>self.channellogs[channel], "%s %s %s <<< %s" % (timestamp, time.tzname[now[-1]], classes, line)
- else:
- print >>self.channellogs[channel], "%s %s <<< %s" % (timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
- elif cmd == "NOTICE":
- if target and (target[0] in IRC.supports["CHANTYPES"] or (len(target) > 1 and target[0] in IRC.supports["PREFIX"][1] and target[1] in IRC.supports["CHANTYPES"])):
- if target[0] in IRC.supports["PREFIX"][1]:
- channel = IRC.channel(target[1:])
- else:
- channel = IRC.channel(target)
- if ident and host:
- user = IRC.user(origin)
- classes = " ".join([modemapping[mode] for mode in IRC.supports["PREFIX"][0] if mode in channel.modes.keys() and user in channel.modes[mode]])
- else:
- classes = "server"
- if classes:
- print >>self.channellogs[channel], "%s %s %s <<< %s" % (timestamp, time.tzname[now[-1]], classes, line)
- else:
- print >>self.channellogs[channel], "%s %s <<< %s" % (timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
- elif target.lower() == IRC.identity.nick.lower() and not ident and not host:
- print >>self.consolelogs[IRC], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.consolelogs[IRC].flush()
- elif cmd == "TOPIC":
- channel = IRC.channel(target)
- print >>self.channellogs[channel], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
- elif cmd == "PART":
- user = IRC.user(origin)
- channel = IRC.channel(target)
- print >>self.channellogs[channel], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
- if user == IRC.identity:
- self.closeChannelLog(channel)
- elif cmd == "KICK":
- kicked = IRC.user(params)
- channel = IRC.channel(target)
- print >>self.channellogs[channel], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
- if kicked == IRC.identity:
- self.closeChannelLog(channel)
- elif cmd == "MODE":
- if target and target[0] in IRC.supports["CHANTYPES"]:
- channel = IRC.channel(target)
- print >>self.channellogs[channel], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
+ print >>self.logs[channel], "%s <<< :%s!%s@%s PRIVMSG %s%s :%s" % (ts, user.nick, user.username, user.host, targetprefix, channel.name, msg)
+ elif type(user) in (str, unicode):
+ classes = "server"
+ print >>self.logs[channel], "%s %s <<< :%s PRIVMSG %s%s :%s" % (ts,
+ classes, user, targetprefix, channel.name, msg)
+ self.logs[channel].flush()
+
+ def onChanAction(self, IRC, user, channel, targetprefix, action):
+ self.onChanMsg(IRC, user, channel, targetprefix,
+ "\x01ACTION %s\x01"%action)
+
+ def onChanNotice(self, IRC, origin, channel, targetprefix, msg):
+ ### Called when someone sends a NOTICE to channel.
+ ts = irc.timestamp()
+ if type(origin) == irc.User:
+ classes = " ".join([modemapping[mode] for mode in IRC.supports["PREFIX"][0] if mode in channel.modes.keys() and origin in channel.modes[mode]])
+ if classes:
+ print >>self.logs[channel], "%s %s <<< :%s!%s@%s NOTICE %s%s :%s" % (ts, classes, origin.nick, origin.username, origin.host, targetprefix, channel.name, msg)
else:
- print >>self.consolelogs[IRC], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.consolelogs[IRC].flush()
- elif cmd in ("NICK", "QUIT"):
- user = IRC.user(origin)
- for channel in user.channels:
- print >>self.channellogs[channel], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.channellogs[channel].flush()
+ print >>self.logs[channel], "%s <<< :%s!%s@%s NOTICE %s%s :%s" % (ts, origin.nick, origin.username, origin.host, targetprefix, channel.name, msg)
+ elif type(origin) in (str, unicode):
+ classes = "server"
+ print >>self.logs[channel], "%s %s <<< :%s NOTICE %s%s :%s" % (ts,
+ classes, origin, targetprefix, channel.name, msg)
+ self.logs[channel].flush()
+
+ def onPart(self, IRC, user, channel, partmsg):
+ ### Called when somebody parts the channel, includes bot.
+ ts = irc.timestamp()
+ if partmsg:
+ print >>self.logs[channel], "%s <<< :%s!%s@%s PART %s :%s" % (ts, user.nick, user.username, user.host, channel.name, partmsg)
else:
- print >>self.consolelogs[IRC], "%s %s <<< %s" % (
- timestamp, time.tzname[now[-1]], line)
- self.consolelogs[IRC].flush()
+ print >>self.logs[channel], "%s <<< :%s!%s@%s PART %s" % (ts,
+ user.nick, user.username, user.host, channel.name)
+ self.logs[channel].flush()
+ if user == IRC.identity:
+ self.closeLog(channel)
- def onConnectAttempt(self, IRC):
- if IRC not in self.consolelogs.keys() or (not self.consolelogs[IRC]) or self.consolelogs[IRC].closed:
- self.openConsoleLog(IRC)
- now = time.localtime()
- timestamp = reduce(lambda x, y: x+":"+y, [str(t).rjust(2,
- "0") for t in now[0:6]])
- print >>self.consolelogs[IRC], "%s %s *** Attempting connection to %s:%s." % (timestamp, time.tzname[now[-1]], IRC.server, IRC.port)
+ def onKick(self, IRC, kicker, channel, kicked, kickmsg):
+ ### Called when somebody is kicked from the channel, includes bot.
+ ts = irc.timestamp()
+ if kickmsg:
+ print >>self.logs[channel], "%s <<< :%s!%s@%s KICK %s %s :%s" % (ts, kicker.nick, kicker.username, kicker.host, channel.name, kicked.nick, kickmsg)
+ else:
+ print >>self.logs[channel], "%s <<< :%s!%s@%s KICK %s %s" % (ts, user.nick, user.username, user.host, channel.name, kicked.nick)
+ self.logs[channel].flush()
+ if user == IRC.identity:
+ self.closeLog(channel)
- def onConnect(self, IRC):
- if IRC not in self.consolelogs.keys() or (not self.consolelogs[IRC]) or self.consolelogs[IRC].closed:
- self.openConsoleLog(IRC)
- #self.openConsoleLog(IRC)
- now = time.localtime()
- timestamp = reduce(lambda x, y: x+":"+y, [str(t).rjust(2,
- "0") for t in now[0:6]])
- print >>self.consolelogs[IRC], "%s %s *** Connection to %s:%s established." % (timestamp, time.tzname[now[-1]], IRC.server, IRC.port)
+ def onSendChanMsg(self, IRC, origin, channel, targetprefix, msg):
+ ### Called when bot sends a PRIVMSG to channel.
+ ### The variable origin refers to a class instance voluntarily identifying itself as that which requested data be sent.
+ ts = irc.timestamp()
+ classes = " ".join([modemapping[mode] for mode in IRC.supports["PREFIX"][0] if mode in channel.modes.keys() and IRC.identity in channel.modes[mode]])
+ if classes:
+ print >>self.logs[channel], "%s %s >>> :%s!%s@%s PRIVMSG %s%s :%s" % (ts, classes, IRC.identity.nick, IRC.identity.username, IRC.identity.host, targetprefix, channel.name, msg)
+ else:
+ print >>self.logs[channel], "%s >>> :%s!%s@%s PRIVMSG %s%s :%s" % (ts, IRC.identity.nick, IRC.identity.username, IRC.identity.host, targetprefix, channel.name, msg)
+ self.logs[channel].flush()
- def onDisconnect(self, IRC):
- now = time.localtime()
- timestamp = reduce(lambda x, y: x+":"+y, [str(t).rjust(2,
- "0") for t in now[0:6]])
- for channel in IRC.identity.channels:
- print >>self.channellogs[channel], "%s %s *** Connection to %s:%s terminated." % (timestamp, time.tzname[now[-1]], IRC.server, IRC.port)
- self.channellogs[channel].flush()
- self.closeChannelLog(channel)
- print >>self.consolelogs[IRC], "%s %s *** Connection %s:%s terminated." % (timestamp, time.tzname[now[-1]], IRC.server, IRC.port)
- self.consolelogs[IRC].flush()
- self.closeConsoleLog(IRC)
-
- def onSend(self, IRC, line, data, origin):
- modemapping = dict(Y="ircop", q="owner", a="admin", o="op",
- h="halfop", v="voice")
- now = time.localtime()
- timestamp = reduce(lambda x, y: x+":"+y, [str(t).rjust(2,
- "0") for t in now[0:6]])
- (cmd, target, params, extinfo) = data
- if IRC.registered and cmd == "PRIVMSG" and "CHANTYPES" in IRC.supports.keys() and len(target) and target[0] in IRC.supports["CHANTYPES"]:
- channel = IRC.channel(target)
- if channel in IRC.identity.channels:
- classes = " ".join([modemapping[mode] for mode in IRC.supports["PREFIX"][0] if mode in channel.modes.keys() and IRC.identity in channel.modes[mode]])
- if classes:
- print >>self.channellogs[channel], "%s %s %s >>> :%s!%s@%s %s" % (timestamp, time.tzname[now[-1]], classes, IRC.identity.nick, IRC.identity.idnt, IRC.identity.host, line)
- else:
- print >>self.channellogs[channel], "%s %s >>> :%s!%s@%s %s" % (timestamp, time.tzname[now[-1]], IRC.identity.nick, IRC.identity.idnt, IRC.identity.host, line)
- self.channellogs[channel].flush()
+ def onSendChanAction(self, IRC, origin, channel, targetprefix, action):
+ ### origin is the source of the channel message
+ ### Called when bot sends an action (/me) to channel.
+ ### The variable origin refers to a class instance voluntarily identifying itself as that which requested data be sent.
+ self.onSendChanMsg(IRC, origin, channel, targetprefix,
+ "\x01ACTION %s\x01"%action)
+
+ def onPrivMsg(self, IRC, user, msg):
+ ### Called when someone sends a PRIVMSG to the bot.
+ if user not in self.logs.keys():
+ self.openLog(user)
+ ts = irc.timestamp()
+ print >>self.logs[user], "%s <<< :%s!%s@%s PRIVMSG %s :%s" % (ts, user.nick, user.username, user.host, IRC.identity.nick, msg)
+ self.logs[user].flush()
+
+ def onPrivNotice(self, IRC, origin, msg):
+ ### Called when someone sends a NOTICE to the bot.
+ ts = irc.timestamp()
+ if type(origin) == irc.User:
+ if origin not in self.logs.keys():
+ self.openLog(origin)
+ print >>self.logs[origin], "%s <<< :%s!%s@%s NOTICE %s :%s" % (ts, origin.nick, origin.username, origin.host, IRC.identity.nick, msg)
+ self.logs[origin].flush()
+ else:
+ print >>self.logs[IRC], "%s <<< :%s NOTICE %s :%s" % (
+ ts, origin, IRC.identity.nick, msg)
+ self.logs[IRC].flush()
+
+ def onPrivAction(self, IRC, user, action):
+ ### Called when someone sends an action (/me) to the bot.
+ self.onPrivMsg(IRC, user, "\x01ACTION %s\x01"%action)
+
+ def onSendPrivMsg(self, IRC, origin, user, msg):
+ ### Called when bot sends a PRIVMSG to a user.
+ ### The variable origin refers to a class instance voluntarily identifying itself as that which requested data be sent.
+ if user not in self.logs.keys():
+ self.openLog(user)
+ ts = irc.timestamp()
+ print >>self.logs[user], "%s >>> :%s!%s@%s PRIVMSG %s :%s" % (ts, IRC.identity.nick, IRC.identity.username, IRC.identity.host, user.nick, msg)
+ self.logs[user].flush()
+
+ def onSendPrivAction(self, IRC, origin, user, action):
+ ### Called when bot sends an action (/me) to a user.
+ ### The variable origin refers to a class instance voluntarily identifying itself as that which requested data be sent.
+ self.onSendPrivMsg(IRC, origin, user, "\x01ACTION %s\x01"%action)
+
+ def onNickChange(self, IRC, user, newnick):
+ ### Called when somebody changes nickname.
+ ts = irc.timestamp()
+ line = "%s <<< :%s!%s@%s NICK %s" % (
+ ts, user.nick, user.username, user.host, newnick)
+
+ ### Print nick change in each channel the user is in.
+ for channel in user.channels:
+ print >>self.logs[channel], line
+ self.logs[channel].flush()
+
+ ### And in the query if open.
+ if user in self.logs.keys():
+ print >>self.logs[user], line
+ self.logs[user].flush()
+
+ def onMeNickChange(self, IRC, newnick):
+ ### Called when the bot changes nickname.
+
+ ### Print nick change to all open queries, except for query with self (already done with onNickChange).
+ ts = irc.timestamp()
+ line = "%s <<< :%s!%s@%s NICK %s" % (ts, IRC.identity.nick,
+ IRC.identity.username, IRC.identity.host, newnick)
+ for (window, log) in self.logs.items():
+ if type(window) == irc.User and window != IRC.identity:
+ print >>log, line
+ log.flush()
+
+ def onQuit(self, IRC, user, quitmsg):
+ ### Called when somebody quits IRC.
+ ts = irc.timestamp()
+ if quitmsg:
+ line = "%s <<< :%s!%s@%s QUIT :%s" % (
+ ts, user.nick, user.username, user.host, quitmsg)
+ else:
+ line = "%s <<< :%s!%s@%s QUIT" % (
+ ts, user.nick, user.username, user.host)
+
+ ### Print quit in each channel the user was in.
+ for channel in user.channels:
+ if channel in self.logs.keys() and not self.logs[channel].closed:
+ print >>self.logs[channel], line
+ self.logs[channel].flush()
+
+ ### And in the query if open.
+ if user in self.logs.keys():
+ print >>self.logs[user], line
+ self.logs[user].flush()
+ self.closeLog(user)
+
+ def onNames(self, IRC, origin, channel, flag, channame, nameslist):
+ ### Called when a NAMES list is received.
+ if channel in self.logs.keys() and not self.logs[channel].closed:
+ log = self.logs[channel]
+ else:
+ log = self.logs[IRC]
+ ts = irc.timestamp()
+
+ secret = "s" in channel.modes.keys() and channel.modes["s"]
+ private = "p" in channel.modes.keys() and channel.modes["p"]
+ modes, symbols = channel.context.supports["PREFIX"]
+ print >>log, "%s <<< :%s 353 %s %s %s :%s" % (ts, origin, IRC.identity.nick, flag, channame,
+ " ".join(["%s%s!%s@%s"%(prefix, nick, username, host) if username and host else "%s%s"%(prefix, nick) for (prefix, nick, username, host) in nameslist]))
+ log.flush()
+
+ def onNamesEnd(self, IRC, origin, channel, channame, endmsg):
+ if channel in self.logs.keys() and not self.logs[channel].closed:
+ log = self.logs[channel]
+ else:
+ log = self.logs[IRC]
+ ts = irc.timestamp()
+ print >>log, "%s <<< :%s 366 %s %s :%s" % (
+ ts, origin, IRC.identity.nick, channame, endmsg)
+ log.flush()
+
+ def onWhoisStart(self, IRC, origin, user, nickname, username, host, realname):
+ ### Called when a WHOIS reply is received.
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 311 %s %s %s %s * :%s" % (irc.timestamp(), origin, IRC.identity.nick, nickname, username, host, realname)
+
+ def onWhoisRegisteredNick(self, IRC, origin, user, nickname, msg):
+ ### Called when a WHOIS reply is received.
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 307 %s %s :%s" % (
+ irc.timestamp(), origin, IRC.identity.nick, nickname, msg)
+
+ def onWhoisAway(self, IRC, origin, user, nickname, awaymsg):
+ ### Called when a WHOIS reply is received.
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 301 %s %s :%s" % (irc.timestamp(
+ ), origin, IRC.identity.nick, nickname, awaymsg)
+
+ def onWhoisConnectingFrom(self, IRC, origin, user, nickname, msg):
+ ### Called when a WHOIS reply is received.
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 378 %s %s :%s" % (
+ irc.timestamp(), origin, IRC.identity.nick, nickname, msg)
+
+ def onWhoisChannels(self, IRC, origin, user, nickname, chanlist):
+ ### Called when a WHOIS reply is received.
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 319 %s %s :%s" % (irc.timestamp(),
+ origin, IRC.identity.nick, nickname, " ".join(chanlist))
+
+ def onWhoisAvailability(self, IRC, origin, user, nickname, msg):
+ ### Called when a WHOIS reply is received.
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 310 %s %s :%s" % (
+ irc.timestamp(), origin, IRC.identity.nick, nickname, msg)
+
+ def onWhoisServer(self, IRC, origin, user, nickname, server, servername):
+ ### Called when a WHOIS reply is received.
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 312 %s %s %s :%s" % (irc.timestamp(), origin, IRC.identity.nick, nickname, server, servername)
+
+ def onWhoisOp(self, IRC, origin, user, nickname, msg):
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 313 %s %s :%s" % (
+ irc.timestamp(), origin, IRC.identity.nick, nickname, msg)
+
+ def onWhoisTimes(self, IRC, origin, user, nickname, idletime, signontime, msg):
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 317 %s %s %d %d :%s" % (irc.timestamp(), origin, IRC.identity.nick, nickname, idletime, signontime, msg)
+
+ def onWhoisSSL(self, IRC, origin, user, nickname, msg):
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 671 %s %s :%s" % (
+ irc.timestamp(), origin, IRC.identity.nick, nickname, msg)
+
+ def onWhoisModes(self, IRC, origin, user, nickname, msg):
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 339 %s %s :%s" % (
+ irc.timestamp(), origin, IRC.identity.nick, nickname, msg)
+
+ def onWhoisLoggedInAs(self, IRC, origin, user, nickname, loggedinas, msg):
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 330 %s %s %s :%s" % (irc.timestamp(), origin, IRC.identity.nick, nickname, loggedinas, msg)
+
+ def onWhoisEnd(self, IRC, origin, user, nickname, msg):
+ if user not in self.logs.keys():
+ self.openLog(user)
+ print >>self.logs[user], "%s <<< :%s 318 %s %s :%s" % (
+ irc.timestamp(), origin, IRC.identity.nick, nickname, msg)
+ self.logs[user].flush()
+
+ def onWhoEntry(self, IRC, **kwargs):
+ ### Called when a WHO list is received.
+ pass
+
+ def onWhoEnd(self, IRC, **kwargs):
+ ### Called when a WHO list is received.
+ pass
+
+ def onList(self, IRC, chanlistbegin, chanlist, endmsg):
+ ### Called when a channel list is received.
+ pass
+
+ def onTopic(self, IRC, origin, channel, topic):
+ ### Called when channel topic is received via 332 response.
+ ts = irc.timestamp()
+ if channel in self.logs.keys() and not self.logs[channel].closed:
+ log = self.logs[channel]
+ else:
+ log = self.logs[IRC]
+ print >>log, "%s <<< :%s 332 %s %s :%s" % (
+ ts, origin, IRC.identity.nick, channel.name, topic)
+ log.flush()
+
+ def onTopicInfo(self, IRC, origin, channel, topicsetby, topictime):
+ ### Called when channel topic info is received via 333 response.
+ ts = irc.timestamp()
+ if channel in self.logs.keys() and not self.logs[channel].closed:
+ log = self.logs[channel]
+ else:
+ log = self.logs[IRC]
+ print >>log, "%s <<< :%s 333 %s %s %s %d" % (ts, origin,
+ IRC.identity.nick, channel.name, topicsetby, topictime)
+ log.flush()
+
+ def onTopicSet(self, IRC, user, channel, topic):
+ ### Called when channel topic is changed.
+ ts = irc.timestamp()
+ print >>self.logs[channel], "%s <<< :%s!%s@%s TOPIC %s :%s" % (ts,
+ user.nick, user.username, user.host, channel.name, topic)
+ self.logs[channel].flush()
+
+ def onChanModeSet(self, IRC, user, channel, modedelta):
+ ### Called when channel modes are changed.
+ ### modedelta is a list of tuples of the format ("+x", parameter), ("+x", None) if no parameter is provided.
+ ts = irc.timestamp()
+ modestr = ""
+ params = []
+ sign = ""
+ for (sgn, modechar), param in modedelta:
+ if sgn != sign:
+ modestr += sgn
+ sign = sgn
+ modestr += modechar
+ if param is not None:
+ params.append(param.nick if type(param) == irc.User else param)
+ if len(params):
+ if type(user) == irc.User:
+ print >>self.logs[channel], "%s <<< :%s!%s@%s MODE %s %s %s" % (ts, user.nick, user.username, user.host, channel.name, modestr, " ".join(params))
else:
- print >>self.consolelogs[IRC], "%s %s >>> :%s!%s@%s %s" % (timestamp, time.tzname[now[-1]], IRC.identity.nick, IRC.identity.idnt, IRC.identity.host, line)
- self.consolelogs[IRC].flush()
- if IRC.registered and len(target) and (target[0] in IRC.supports["CHANTYPES"] or (len(target) > 1 and target[0] in IRC.supports["PREFIX"][1] and target[1] in IRC.supports["CHANTYPES"])) and cmd == "NOTICE":
- channel = IRC.channel(target[1:] if target[0]
- in IRC.supports["PREFIX"][1] else target)
- if channel in IRC.identity.channels:
- classes = " ".join([modemapping[mode] for mode in IRC.supports["PREFIX"][0] if mode in channel.modes.keys() and IRC.identity in channel.modes[mode]])
- if classes:
- print >>self.channellogs[channel], "%s %s %s >>> :%s!%s@%s %s" % (timestamp, time.tzname[now[-1]], classes, IRC.identity.nick, IRC.identity.idnt, IRC.identity.host, line)
- else:
- print >>self.channellogs[channel], "%s %s >>> :%s!%s@%s %s" % (timestamp, time.tzname[now[-1]], IRC.identity.nick, IRC.identity.idnt, IRC.identity.host, line)
- self.channellogs[channel].flush()
+ print >>self.logs[channel], "%s <<< :%s MODE %s %s %s" % (ts, user, channel.name, modestr, " ".join(params))
+ else:
+ if type(user) == irc.User:
+ print >>self.logs[channel], "%s <<< :%s!%s@%s MODE %s %s" % (ts, user.nick, user.username, user.host, channel.name, modestr)
else:
- print >>self.consolelogs[IRC], "%s %s >>> :%s!%s@%s %s" % (timestamp, time.tzname[now[-1]], IRC.identity.nick, IRC.identity.idnt, IRC.identity.host, line)
- self.consolelogs[IRC].flush()
+ print >>self.logs[channel], "%s <<< :%s MODE %s %s" % (
+ ts, user, channel.name, modestr)
+ self.logs[channel].flush()
+
+ def onChannelModes(self, IRC, channel, modedelta):
+ ### Called when channel modes are received via 324 response.
+ ts = irc.timestamp()
+ if channel in self.logs.keys() and not self.logs[channel].closed:
+ log = self.logs[channel]
+ else:
+ log = self.logs[IRC]
+ modestr = ""
+ params = []
+ sign = ""
+ for (sgn, modechar), param in modedelta:
+ if sgn != sign:
+ modestr += sgn
+ sign = sgn
+ modestr += modechar
+ if param is not None:
+ params.append(param)
+ if len(params):
+ print >>log, "%s <<< :%s 324 %s %s %s %s" % (ts, IRC.serv, IRC.identity.nick, channel.name, modestr, " ".join(params))
+ else:
+ print >>log, "%s <<< :%s 324 %s %s %s" % (ts, IRC.serv,
+ IRC.identity.nick, channel.name, modestr)
+ log.flush()
+
+ def onChanCreated(self, IRC, channel, created):
+ ### Called when a 329 response is received.
+ ts = irc.timestamp()
+ if channel in self.logs.keys() and not self.logs[channel].closed:
+ log = self.logs[channel]
+ else:
+ log = self.logs[IRC]
+ print >>log, "%s <<< :%s 329 %s %s %d" % (
+ ts, IRC.serv, IRC.identity.nick, channel.name, created)
+ log.flush()
+
+ def onUnhandled(self, IRC, line, origin, cmd, target, params, extinfo):
+ ts = irc.timestamp()
+ print >>self.logs[IRC], "%s <<< %s" % (ts, line)
+ self.logs[IRC].flush()