Ticket #3230: ticket3230.patch
File ticket3230.patch, 10.7 KB (added by , 14 years ago) |
---|
-
twisted/words/test/test_irc.py
160 160 del self.client 161 161 del self.transport 162 162 163 def testModeChange(self): 164 message = ":ChanServ!ChanServ@services. MODE #tanstaafl +o exarkun\r\n" 163 164 def _sendModeChange(self, msg, args=''): 165 """ 166 Format the string and send it to the client 167 """ 168 message = ":Wolf!~wolf@yok.utu.fi MODE #chan %s %s\r\n" % (msg, args) 165 169 self.client.dataReceived(message) 166 self.assertEquals(167 self.client.calls,168 [('modeChanged', {'user': "ChanServ!ChanServ@services.",169 'channel': '#tanstaafl',170 'set': True,171 'modes': 'o',172 'args': ('exarkun',)})])173 170 171 172 def _parseModeChange(self, results): 173 """ 174 Parse the results, do some test and return the data to check 175 """ 176 for n,result in enumerate(results): 177 method, data = result 178 self.assertEquals(method, 'modeChanged') 179 self.assertEquals(data['user'], 'Wolf!~wolf@yok.utu.fi') 180 self.assertEquals(data['channel'], '#chan') 181 results[n] = tuple([data[key] for key in ('set', 'modes', 'args')]) 182 return results 183 184 185 def _checkModeChange(self, expected): 186 """ 187 Compare the expected result with the one returned by the client 188 """ 189 result = self._parseModeChange(self.client.calls) 190 self.assertEquals(result, expected) 191 192 193 def test_modeChangeWithASingleMode(self): 194 """ 195 A single mode added to a user 196 """ 197 self._sendModeChange('+o', 'exarkun') 198 self._checkModeChange([(True, 'o', ('exarkun',))]) 199 200 201 def test_modeChangeWithArgsAndDifferentModes(self): 202 """ 203 Two modes added and one removed, they all accept args 204 """ 205 self._sendModeChange('-oo+b', 'foo bar baz') 206 self._checkModeChange([ 207 (True, 'b', ('baz',)), 208 (False, 'oo', ('foo', 'bar')) 209 ]) 210 211 212 def test_modeChangeWithArgsAndEqualModes(self): 213 """ 214 Two modes added, they all accept args 215 """ 216 self._sendModeChange('+xy', 'cow frog') 217 self._checkModeChange([(True, 'xy', ('cow', 'frog'))]) 218 219 220 def test_modeChangeWithArgsAndMixedModes(self): 221 """ 222 Some modes added and others removed, they all accept args 223 """ 224 self._sendModeChange('+oo-h+vv-b', 'foo bar baz cow frog bat') 225 self._checkModeChange([ 226 (True, 'oovv', ('foo','bar','cow','frog')), 227 (False, 'hb', ('baz', 'bat')) 228 ]) 229 230 231 def test_modeChangeWithNoArgsAndDifferentModes(self): 232 """ 233 A mode added and another removed, they don't accept any arg 234 """ 235 self._sendModeChange('-c+U') 236 self._checkModeChange([(True, 'U', ()), (False, 'c', ())]) 237 238 239 def test_modeChangeWithNoArgsAndEqualModes(self): 240 """ 241 Two modes removed, they don't accept any arg 242 """ 243 self._sendModeChange('-cU') 244 self._checkModeChange([(False, 'cU', ())]) 245 246 247 def test_modeChangeWithNoArgsAndMixedModes(self): 248 """ 249 Some modes added and others removed, they don't accept any arg 250 """ 251 self._sendModeChange('-c+fr-o+og-w') 252 self._checkModeChange([(True, 'frog', ()), (False, 'cow', ())]) 253 254 255 def test_modeChangeWithSomeArgAndDifferentModes(self): 256 """ 257 Two modes added and two removed, only the last accepts an arg 258 """ 259 self._sendModeChange('+sU-lv', 'dea7h') 260 self._checkModeChange([(True, 'sU', ()), (False, 'lv', ('dea7h',))]) 261 262 263 def test_modeChangeWithSomeArgAndEqualModes(self): 264 """ 265 Two modes added, only the last accepts an arg 266 """ 267 self._sendModeChange('+cl 1337') 268 self._checkModeChange([(True, 'cl', ('1337',))]) 269 270 271 def test_modeChangeWithSomeArgAndMixedModes(self): 272 """ 273 Some modes added and others removed, only the 2nd, 3rd and 5th 274 accept an arg 275 """ 276 self._sendModeChange('-co+l-U+o', 'Wolf 3141592 dea7h') 277 self._checkModeChange([ 278 (True, 'lo', ('3141592', 'dea7h')), 279 (False, 'coU', ('Wolf',)) 280 ]) 281 282 283 def test_modeChangeWithUnknownModes(self): 284 """ 285 Some modes added and others removed, only the 3rd is known to 286 accept an arg, the other modes don't accept anything by default 287 """ 288 self._sendModeChange('+a-eo+f-g+qz', 'Wolf') 289 self._checkModeChange([(True, 'afqz', ()), (False, 'eog', ('Wolf',))]) 290 291 292 def test_modeChangeWithWrongModesString(self): 293 """ 294 The modes string is supposed to start with '+' or '-', if they miss 295 a '+' will be added by default 296 """ 297 self._sendModeChange('o', 'Wolf') 298 self._checkModeChange([(True, 'o', ('Wolf',))]) 299 300 301 def test_modeChangeWithRepeatedAddedModes(self): 302 """ 303 Two modes are added repeating the '+' 304 """ 305 self._sendModeChange('+o+c', 'Wolf') 306 self._checkModeChange([(True, 'oc', ('Wolf',))]) 307 308 309 def test_modeChangeWithRepeatedRemovedModes(self): 310 """ 311 Two modes are removed repeating the '-' 312 """ 313 self._sendModeChange('-o-c', 'Wolf') 314 self._checkModeChange([(False, 'oc', ('Wolf',))]) 315 316 317 def test_modeChangeWithRepeatedMixedModes(self): 318 """ 319 Several modes are added and removed repeating the '+' and the '-' 320 """ 321 self._sendModeChange('+a+v-h-r+o+c-k-l', 'Wolf dea7h Svadilfari') 322 self._checkModeChange([ 323 (True, 'avoc', ('Wolf', 'Svadilfari')), 324 (False, 'hrkl', ('dea7h',)) 325 ]) 326 327 174 328 def _serverTestImpl(self, code, msg, func, **kw): 175 329 host = pop(kw, 'host', 'server.host') 176 330 nick = pop(kw, 'nick', 'nickname') -
twisted/words/protocols/irc.py
549 549 dcc_destdir = '.' 550 550 dcc_sessions = None 551 551 552 # 'mode': (added, removed) i.e.: 553 # 'l': (True, False) accepts an arg when added and no arg when removed 554 # from http://www.faqs.org/rfcs/rfc1459.html - 4.2.3.1 Channel modes 555 # if you want other modes to accept args, add them here, by default unknown 556 # modes won't accept any arg 557 _modeAcceptsArg = { 558 'o': (True, True), # op/deop a user 559 'h': (True, True), # hop/dehop (halfop) a user (not defined in RFC) 560 'v': (True, True), # voice/devoice a user 561 'b': (True, True), # ban/unban a user/mask 562 'l': (True, False), # set the user limit to channel 563 'k': (True, False), # set a channel key (password) 564 't': (False, False), # only ops set topic 565 's': (False, False), # secret channel 566 'p': (False, False), # private channel 567 'i': (False, False), # invite-only channel 568 'm': (False, False), # moderated channel 569 'n': (False, False), # no external messages 570 } 571 552 572 # If this is false, no attempt will be made to identify 553 573 # ourself to the server. 554 574 performLogin = 1 … … 699 719 self.privmsg(user, channel, message) 700 720 701 721 def modeChanged(self, user, channel, set, modes, args): 702 """Called when a channel's modes are changed722 """Called when users or channel's modes are changed. 703 723 704 724 @type user: C{str} 705 725 @param user: The user and hostmask which instigated this change. 706 726 707 727 @type channel: C{str} 708 @param channel: The channel for which the modes are changing. 728 @param channel: The channel where the modes are changed. If args is 729 empty the channel for which the modes are changing. If the changes are 730 at server level it could be equal to C{user}. 709 731 710 732 @type set: C{bool} or C{int} 711 @param set: true if the mode is being added, false if it is being 712 removed. 733 @param set: True if the mode(s) is being added, False if it is being 734 removed. If some modes are added and others removed at the same time 735 this function will be called twice, the first time with all the added 736 modes, the second with the removed ones. (To change this behaviour 737 override the irc_MODE method) 713 738 714 739 @type modes: C{str} 715 740 @param modes: The mode or modes which are being changed. … … 1011 1036 nick = string.split(prefix,'!')[0] 1012 1037 self.userQuit(nick, params[0]) 1013 1038 1039 1014 1040 def irc_MODE(self, prefix, params): 1015 channel, rest = params[0], params[1:] 1016 set = rest[0][0] == '+' 1017 modes = rest[0][1:] 1018 args = rest[1:] 1019 self.modeChanged(prefix, channel, set, modes, tuple(args)) 1041 """ 1042 Parse the server message when one or more modes are changed 1043 """ 1044 user, channel, modes, args = prefix, params[0], params[1], params[2:] 1045 if modes[0] not in '+-': 1046 # add a '+' before the modes if it isn't specified (e.g. MODE s) 1047 modes = '+' + modes 1048 if ((modes[0] == '+' and '-' not in modes[1:]) or 1049 (modes[0] == '-' and '+' not in modes[1:])): 1050 # all modes are added or removed 1051 set = (modes[0] == '+') 1052 modes = modes[1:].replace('-+'[set], '') 1053 self.modeChanged(user, channel, set, modes, tuple(args)) 1054 else: 1055 # some modes added and other removed 1056 modes2, args2 = ['', ''], [[], []] 1057 for c in modes: 1058 if c == '+': 1059 i = 0 1060 elif c == '-': 1061 i = 1 1062 else: 1063 modes2[i] += c 1064 # take an arg only if the mode accepts it (e.g. +o nick) 1065 if args and self._modeAcceptsArg.get(c, (False, False))[i]: 1066 args2[i].append(args.pop(0)) 1067 if args: 1068 log.msg('Too many args (%s) received for %s. If one or more ' 1069 'modes are supposed to accept an arg and they are not in ' 1070 '_modeAcceptsArg, add them.' % (' '.join(args), modes)) 1020 1071 1072 self.modeChanged(user, channel, True, modes2[0], tuple(args2[0])) 1073 self.modeChanged(user, channel, False, modes2[1], tuple(args2[1])) 1074 1075 1021 1076 def irc_PING(self, prefix, params): 1022 1077 self.sendLine("PONG %s" % params[-1]) 1023 1078