from __future__ import print_function
-import os, sys, select, MySQLdb, MySQLdb.cursors, time, random, gc
+import os, sys, select, MySQLdb, MySQLdb.cursors, time, traceback, random, gc
import bot, config, ctlmod
class Erebus(object): #singleton to pass around
numhandlers = {}
msghandlers = {}
chanhandlers = {}
+ exceptionhandlers = [] # list of (Exception_class, handler_function) tuples
users = {}
chans = {}
class User(object):
def __init__(self, nick, auth=None):
self.nick = nick
- self.auth = auth
+ if auth is None:
+ self.auth = None
+ else:
+ self.auth = auth.lower()
self.checklevel()
self.chans = []
self.glevel = 0
return self.glevel
+ def setlevel(self, level, savetodb=True):
+ if savetodb:
+ if level != 0:
+ c = main.query("REPLACE INTO users (auth, level) VALUES (%s, %s)", (self.auth, level))
+ else:
+ c = main.query("DELETE FROM users WHERE auth = %s", (self.auth,))
+ if c == 0: # no rows affected
+ c = True # is fine
+ if c:
+ self.glevel = level
+ return True
+ else:
+ return False
+ else:
+ self.glevel = level
+ return True
+
def join(self, chan):
if chan not in self.chans: self.chans.append(chan)
def part(self, chan):
return True
else:
return False
+ else:
+ self.levels[auth] = level
+ return True
def userjoin(self, user, level=None):
if user not in self.users: self.users.append(user)
def __repr__(self): return "<Channel %r>" % (self.name)
def __init__(self, cfg):
+ self.mustquit = None
self.starttime = time.time()
self.cfg = cfg
self.trigger = cfg.trigger
self.po.register(fileno, select.POLLIN)
elif self.potype == "select":
self.fdlist.append(fileno)
+ def delfd(self, fileno):
+ del self.fds[fileno]
+ if self.potype == "poll":
+ self.po.unregister(fileno)
+ elif self.potype == "select":
+ self.fdlist.remove(fileno)
def bot(self, name): #get Bot() by name (nick)
return self.bots[name.lower()]
def randbot(self): #get Bot() randomly
return self.bots[random.choice(list(self.bots.keys()))]
- def user(self, _nick, justjoined=False, create=True):
+ def user(self, _nick, send_who=False, create=True):
nick = _nick.lower()
+
+ if send_who and (nick not in self.users or not self.users[nick].isauthed()):
+ self.randbot().conn.send("WHO %s n%%ant,1" % (nick))
+
if nick in self.users:
return self.users[nick]
elif create:
user = self.User(_nick)
self.users[nick] = user
-
- if justjoined:
- self.randbot().conn.send("WHO %s n%%ant,1" % (nick))
-
return user
else:
return None
return chan
def poll(self):
+ timeout_seconds = 30
if self.potype == "poll":
- return [fd for (fd, ev) in self.po.poll()]
+ pollres = self.po.poll(timeout_seconds * 1000)
+ return [fd for (fd, ev) in pollres]
elif self.potype == "select":
- return select.select(self.fdlist, [], [])[0]
+ return select.select(self.fdlist, [], [], timeout_seconds)[0]
def connectall(self):
for bot in self.bots.values():
def getchanhook(self, chan):
return self.chanhandlers[chan]
+ def hookexception(self, exc, handler):
+ self.exceptionhandlers.append((exc, handler))
+ def unhookexception(self, exc, handler):
+ self.exceptionhandlers.remove((exc, handler))
+ def hasexceptionhook(self, exc):
+ return any((True for x,h in self.exceptionhandlers if isinstance(exc, x)))
+ def getexceptionhook(self, exc):
+ return (h for x,h in self.exceptionhandlers if isinstance(exc, x))
+
def dbsetup():
main.db = None
def loop():
poready = main.poll()
for fileno in poready:
- for line in main.fd(fileno).getdata():
- main.fd(fileno).parse(line)
+ try:
+ data = main.fd(fileno).getdata()
+ except:
+ main.log('*', '!', 'Super-mega-emergency: getdata raised exception for socket %d' % (fileno))
+ traceback.print_exc()
+ data = None
+ if data is None:
+ main.fd(fileno).close()
+ else:
+ for line in data:
+ if cfg.getboolean('debug', 'io'):
+ main.log(str(main.fd(fileno)), 'I', line)
+ try:
+ main.fd(fileno).parse(line)
+ except:
+ main.log('*', '!', 'Super-mega-emergency: parse raised exception for socket %d data %r' % (fileno, line))
+ traceback.print_exc()
+ if main.mustquit is not None:
+ main.log('*', '!', 'Core exiting due to: %s' % (main.mustquit))
+ raise main.mustquit
if __name__ == '__main__':
try: os.rename('logfile', 'oldlogs/%s' % (time.time()))