X-Git-Url: https://jfr.im/git/erebus.git/blobdiff_plain/06a27ea53b2283e7bc5dcff3e64a1707241bd4a5..84b7c247d55c191d6ab898e812a578d304db7989:/bot.py diff --git a/bot.py b/bot.py index 60b2e50..a0510fa 100644 --- a/bot.py +++ b/bot.py @@ -29,6 +29,11 @@ class Bot(object): self.slowmsgqueue = deque() self.makemsgtimer() + def __del__(self): + curs = self.parent.db.cursor() + curs.execute("UPDATE bots SET connected = 0 WHERE nick = %s", (self.nick,)) + curs.close() + def connect(self): if self.conn.connect(): @@ -49,7 +54,8 @@ class Bot(object): one = { #things to look for after source '001': self._got001, 'PRIVMSG': self._gotprivmsg, - '354': self._got354, + '353': self._got353, #NAMES + '354': self._got354, #WHO 'JOIN': self._gotjoin, 'PART': self._gotpart, 'QUIT': self._gotquit, @@ -75,11 +81,19 @@ class Bot(object): self.conn.register() def _gotping(self, pieces): self.conn.send("PONG %s" % (pieces[1])) - def _goterror(self, pieces): #TODO handle better + def _goterror(self, pieces): #TODO handle more gracefully + curs = self.parent.db.cursor() + curs.execute("UPDATE bots SET connected = 0") + curs.close() sys.exit(2) os._exit(2) def _got001(self, pieces): self.conn.registered(True) + + curs = self.parent.db.cursor() + curs.execute("UPDATE bots SET connected = 1 WHERE nick = %s", (self.nick,)) + curs.close() + self.conn.send("MODE %s +x" % (pieces[2])) if self.authname is not None and self.authpass is not None: self.conn.send("AUTH %s %s" % (self.authname, self.authpass)) @@ -91,15 +105,48 @@ class Bot(object): target = pieces[2] msg = ' '.join(pieces[3:])[1:] self.parsemsg(user, target, msg) + def _got353(self, pieces): + chan = self.parent.channel(pieces[4]) + names = pieces[5:] + names[0] = names[0][1:] #remove colon + for n in names: + user = self.parent.user(n.lstrip('@+')) + if n[0] == '@': + chan.userjoin(user, 'op') + elif n[0] == '+': + chan.userjoin(user, 'voice') + else: + chan.userjoin(user) + user.join(chan) def _got354(self, pieces): - qt, nick, auth = pieces[3:6] - self.parent.user(nick).authed(auth) + qt = int(pieces[3]) + if qt < 3: + nick, auth = pieces[4:6] + chan = None + else: + chan, nick, auth = pieces[4:7] + chan = self.parent.channel(chan) + user = self.parent.user(nick) + user.authed(auth) + + if chan is not None: + user.join(chan) + chan.userjoin(user) + + if qt == 2: # triggered by !auth + if user.isauthed(): + if user.glevel > 0: + self.msg(nick, "You are now known as #%s (access level: %s)" % (auth, user.glevel)) + else: + self.msg(nick, "You are now known as #%s (not staff)" % (auth)) + else: + self.msg(nick, "I tried, but you're not authed!") def _gotjoin(self, pieces): nick = pieces[0].split('!')[0][1:] chan = self.parent.channel(pieces[2]) if nick == self.nick: - self.conn.send("WHO %s c%%ant,1" % (chan)) + self.conn.send("WHO %s c%%cant,3" % (chan)) else: user = self.parent.user(nick, justjoined=True) chan.userjoin(user) @@ -109,11 +156,16 @@ class Bot(object): chan = self.parent.channel(pieces[2]) if nick != self.nick: - self.parent.user(nick).part(chan) + gone = self.parent.user(nick).part(chan) chan.userpart(self.parent.user(nick)) + if gone: + self.parent.user(nick).quit() + del self.parent.users[nick.lower()] def _gotquit(self, pieces): nick = pieces[0].split('!')[0][1:] if nick != self.nick: + for chan in self.parent.user(nick).chans: + chan.userpart(self.parent.user(nick)) self.parent.user(nick).quit() del self.parent.users[nick.lower()] def _gotnick(self, pieces): @@ -123,9 +175,30 @@ class Bot(object): self.parent.users[newnick.lower()] = self.parent.users[oldnick.lower()] del self.parent.users[oldnick.lower()] self.parent.users[newnick.lower()].nickchange(newnick) - def _gotmode(self, pieces): #TODO parse for ops/voices (at least) - pass - + def _gotmode(self, pieces): + source = pieces[0].split('!')[0][1:] + chan = self.parent.channel(pieces[2]) + mode = pieces[3] + args = pieces[4:] + + adding = True + for c in mode: + if c == '+': + adding = True + elif c == '-': + adding = False + elif c == 'o': + if adding: + chan.userop(self.parent.user(args.pop(0))) + else: + chan.userdeop(self.parent.user(args.pop(0))) + elif c == 'v': + if adding: + chan.uservoice(self.parent.user(args.pop(0))) + else: + chan.userdevoice(self.parent.user(args.pop(0))) + else: + pass # don't care about other modes def __debug_cbexception(self, source, *args, **kwargs): if int(self.parent.cfg.get('debug', 'cbexc', default=0)) == 1: @@ -168,7 +241,8 @@ class Bot(object): for callback in self.parent.getchanhook(target.lower()): try: cbret = callback(self, user, chan, *pieces) - if cbret is NotImplemented: self.msg(user, "Command not implemented.") + except NotImplementedError: + self.msg(user, "Command not implemented.") except: self.msg(user, "Command failed. Code: CBEXC%09.3f" % (time.time() % 100000)) self.__debug_cbexception("chanhook", user=user, target=target, msg=msg) @@ -185,10 +259,16 @@ class Bot(object): elif user.glevel >= callback.reqglevel and (not callback.needchan or chan.levelof(user.auth) >= callback.reqclevel): try: cbret = callback(self, user, chan, target, *pieces[1:]) - if cbret is NotImplemented: self.msg(user, "Command not implemented.") + except NotImplementedError: + self.msg(user, "Command not implemented.") except Exception: self.msg(user, "Command failed. Code: CBEXC%09.3f" % (time.time() % 100000)) self.__debug_cbexception("hook", user=user, target=target, msg=msg) + except SystemExit as e: + curs = self.parent.db.cursor() + curs.execute("UPDATE bots SET connected = 0") + curs.close() + raise e def __debug_nomsg(self, target, msg): if int(self.parent.cfg.get('debug', 'nomsg', default=0)) == 1: