diff --git a/src/irclib.py b/src/irclib.py index 9d763ad9c..5c505a79f 100644 --- a/src/irclib.py +++ b/src/irclib.py @@ -608,8 +608,13 @@ class IrcState(IrcCommandDispatcher, log.Firewalled): chan.removeUser(user) def doQuit(self, irc, msg): - for channel in self.channels.values(): - channel.removeUser(msg.nick) + channel_names = ircutils.IrcSet() + for (name, channel) in self.channels.items(): + if msg.nick in channel.users: + channel_names.add(name) + channel.removeUser(msg.nick) + # Remember which channels the user was on + msg.tag('channels', channel_names) if msg.nick in self.nicksToHostmasks: # If we're quitting, it may not be. del self.nicksToHostmasks[msg.nick] diff --git a/test/test_irclib.py b/test/test_irclib.py index ca78d6285..f4ae0b52b 100644 --- a/test/test_irclib.py +++ b/test/test_irclib.py @@ -466,6 +466,25 @@ class IrcTestCase(SupyTestCase): self.irc.feedMsg(msg2) self.assertEqual(list(self.irc.state.history), [msg1, msg2]) + def testQuit(self): + self.irc.reset() + self.irc.feedMsg(ircmsgs.IrcMsg(':someuser JOIN #foo')) + self.irc.feedMsg(ircmsgs.IrcMsg(':someuser JOIN #bar')) + class Callback(irclib.IrcCallback): + channels_set = None + def name(self): + return 'testcallback' + def doQuit(self2, irc, msg): + self2.channels_set = msg.tagged('channels') + c = Callback() + self.irc.addCallback(c) + try: + self.irc.feedMsg(ircmsgs.IrcMsg(':someuser QUIT')) + finally: + self.irc.removeCallback(c.name()) + self.assertEqual(c.channels_set, ircutils.IrcSet({'#foo', '#bar'})) + + class IrcCallbackTestCase(SupyTestCase): class FakeIrc: