diff --git a/src/callbacks.py b/src/callbacks.py index f436ce1ac..93815743c 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -327,7 +327,13 @@ class IrcObjectProxy: if self.finished: break if hasattr(cb, 'invalidCommand'): - cb.invalidCommand(self, self.msg, self.args) + try: + cb.invalidCommand(self, self.msg, self.args) + except Exception, e: + cb.log.exception('Uncaught exception in invalidCommand:') + log.warning('Uncaught exception in %s.invalidCommand, ' + 'continuing to call other invalidCommands.' % + cb.name()) def finalEval(self): assert not self.finalEvaled, 'finalEval called twice.' @@ -433,6 +439,7 @@ class IrcObjectProxy: if len(s) < allowedLength: self.irc.queueMsg(reply(msg, s, self.prefixName, self.private,self.notice,self.to)) + self.finished = True return msgs = textwrap.wrap(s, allowedLength-30) # -30 is for "nick:" msgs.reverse() diff --git a/test/test_callbacks.py b/test/test_callbacks.py index 3ed7a3da2..203e36252 100644 --- a/test/test_callbacks.py +++ b/test/test_callbacks.py @@ -323,6 +323,35 @@ class PrivmsgTestCase(ChannelPluginTestCase): def testNoEscapingAttributeErrorFromTokenizeWithFirstElementList(self): self.assertError('[plugin list] list') + class InvalidCommand(callbacks.Privmsg): + def invalidCommand(self, irc, msg, tokens): + irc.reply(msg, 'foo') + + def testInvalidCommandOneReplyOnly(self): + try: + original = conf.replyWhenNotCommand + conf.replyWhenNotCommand = True + self.assertRegexp('asdfjkl', 'not a valid command') + self.irc.addCallback(self.InvalidCommand()) + self.assertResponse('asdfjkl', 'foo') + self.assertNoResponse(' ', 2) + finally: + conf.replyWhenNotCommand = original + + class BadInvalidCommand(callbacks.Privmsg): + def invalidCommand(self, irc, msg, tokens): + s = 'This shouldn\'t keep Misc.invalidCommand from being called' + raise Exception, s + + def testBadInvalidCommandDoesNotKillAll(self): + try: + original = conf.replyWhenNotCommand + conf.replyWhenNotCommand = True + self.irc.addCallback(self.BadInvalidCommand()) + self.assertRegexp('asdfjkl', 'not a valid command') + finally: + conf.replyWhenNotCommand = original + class PrivmsgCommandAndRegexpTestCase(PluginTestCase): plugins = ('Utilities',) # Gotta put something.