diff --git a/src/irclib.py b/src/irclib.py index fe19d0a8b..5d190aa88 100644 --- a/src/irclib.py +++ b/src/irclib.py @@ -80,7 +80,7 @@ class IrcCallback(IrcCommandDispatcher): def __init__(self, *args, **kwargs): super(IrcCallback, self).__init__(*args, **kwargs) - + def __repr__(self): return '<%s %s>' % (self.__class__.__name__, self.name()) @@ -104,7 +104,7 @@ class IrcCallback(IrcCommandDispatcher): assert self not in after, '%s was in its own after.' % self.name() assert self not in before, '%s was in its own before.' % self.name() return (before, after) - + def inFilter(self, irc, msg): """Used for filtering/modifying messages as they're entering. @@ -244,7 +244,7 @@ class ChannelState(object): return nick in self.voices def isHalfop(self, nick): return nick in self.halfops - + def addUser(self, user): "Adds a given user to the ChannelState. Power prefixes are handled." nick = user.lstrip('@%+') @@ -363,7 +363,7 @@ class IrcState(IrcCommandDispatcher): def __reduce__(self): return (self.__class__, (self.history, self.supported, self.nicksToHostmasks, self.channels)) - + def __eq__(self, other): return self.history == other.history and \ self.channels == other.channels and \ @@ -400,7 +400,6 @@ class IrcState(IrcCommandDispatcher): _005converters = utils.InsensitivePreservingDict({ 'modes': int, 'keylen': int, - 'maxbans': int, 'nicklen': int, 'userlen': int, 'hostlen': int, @@ -425,6 +424,34 @@ class IrcState(IrcCommandDispatcher): return dict(zip('ovh', s)) _005converters['prefix'] = _prefixParser del _prefixParser + def _maxlistParser(s): + modes = '' + limits = [] + pairs = s.split(',') + for pair in pairs: + (mode, limit) = pair.split(':', 1) + modes += mode + limits += (int(limit),) * len(mode) + return dict(zip(modes, limits)) + _005converters['maxlist'] = _maxlistParser + del _maxlistParser + def _maxbansParser(s): + # IRCd using a MAXLIST style string (IRCNet) + if ':' in s: + modes = '' + limits = [] + pairs = s.split(',') + for pair in pairs: + (mode, limit) = pair.split(':', 1) + modes += mode + limits += (int(limit),) * len(mode) + d = dict(zip(modes, limits)) + assert 'b' in d + return d['b'] + else: + return int(s) + _005converters['maxbans'] = _maxbansParser + del _maxbansParser def do005(self, irc, msg): for arg in msg.args[1:-1]: # 0 is nick, -1 is "are supported" if '=' in arg: @@ -437,7 +464,7 @@ class IrcState(IrcCommandDispatcher): log.error('Name: %s, Converter: %s', name, converter) else: self.supported[arg] = None - + def do352(self, irc, msg): # WHO reply. (nick, user, host) = (msg.args[5], msg.args[2], msg.args[3]) diff --git a/test/test_irclib.py b/test/test_irclib.py index b4fe078cb..5f05359f8 100644 --- a/test/test_irclib.py +++ b/test/test_irclib.py @@ -236,7 +236,7 @@ class IrcStateTestCase(SupyTestCase): m = ircmsgs.kick('#foo', self.irc.nick, prefix=self.irc.prefix) st.addMsg(self.irc, m) self.failIf('#foo' in st.channels) - + def testAddMsgRemovesOpsProperly(self): st = irclib.IrcState() st.channels['#foo'] = irclib.ChannelState() @@ -283,7 +283,13 @@ class IrcStateTestCase(SupyTestCase): state.addMsg(self.irc, ircmsgs.IrcMsg(':desolate.wasteland.org 005 jemfinch NOQUIT WATCH=128 SAFELIST MODES=6 MAXCHANNELS=10 MAXBANS=100 NICKLEN=30 TOPICLEN=307 KICKLEN=307 CHANTYPES=&# PREFIX=@+ NETWORK=DALnet SILENCE=10 :are available on this server')) self.assertEqual(state.supported['prefix']['o'], '@') self.assertEqual(state.supported['prefix']['v'], '+') - + + def testIRCNet005(self): + state = irclib.IrcState() + # Testing IRCNet's misuse of MAXBANS + state.addMsg(self.irc, ircmsgs.IrcMsg(':irc.inet.tele.dk 005 adkwbot WALLCHOPS KNOCK EXCEPTS INVEX MODES=4 MAXCHANNELS=20 MAXBANS=beI:100 MAXTARGETS=4 NICKLEN=9 TOPICLEN=120 KICKLEN=90 :are supported by this server')) + self.assertEqual(state.supported['maxbans'], 100) + def testEmptyTopic(self): state = irclib.IrcState() state.addMsg(self.irc, ircmsgs.topic('#foo'))