mirror of
				https://github.com/Mikaela/Limnoria.git
				synced 2025-10-30 23:27:24 +01:00 
			
		
		
		
	Merge remote-tracking branch 'supybot/master' into testing
Conflicts: .mailmap README docs/FAQ.rst plugins/Ctcp/plugin.py plugins/Misc/plugin.py plugins/Network/plugin.py plugins/QuoteGrabs/plugin.py plugins/RSS/README.txt plugins/Relay/plugin.py plugins/ShrinkUrl/config.py plugins/ShrinkUrl/plugin.py plugins/ShrinkUrl/test.py setup.py src/callbacks.py src/commands.py src/conf.py test/test_commands.py
This commit is contained in:
		
						commit
						487f8c8af5
					
				| @ -56,8 +56,8 @@ class Admin(callbacks.Plugin): | ||||
|     def do437(self, irc, msg): | ||||
|         """Nick/channel temporarily unavailable.""" | ||||
|         target = msg.args[0] | ||||
|         t = time.time() + 30 | ||||
|         if irc.isChannel(target): # We don't care about nicks. | ||||
|             t = time.time() + 30 | ||||
|             # Let's schedule a rejoin. | ||||
|             networkGroup = conf.supybot.networks.get(irc.network) | ||||
|             def rejoin(): | ||||
| @ -67,6 +67,16 @@ class Admin(callbacks.Plugin): | ||||
|             schedule.addEvent(rejoin, t) | ||||
|             self.log.info('Scheduling a rejoin to %s at %s; ' | ||||
|                           'Channel temporarily unavailable.', target, t) | ||||
|         else: | ||||
|             irc = self.pendingNickChanges.get(irc, None) | ||||
|             if irc is not None: | ||||
|                 def nick(): | ||||
|                     irc.queueMsg(ircmsgs.nick(target)) | ||||
|                 schedule.addEvent(nick, t) | ||||
|                 self.log.info('Scheduling a nick change to %s at %s; ' | ||||
|                               'Nick temporarily unavailable.', target, t) | ||||
|             else: | ||||
|                 self.log.debug('Got 437 without Admin.nick being called.') | ||||
| 
 | ||||
|     def do471(self, irc, msg): | ||||
|         try: | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| ### | ||||
| # Copyright (c) 2002-2004, Jeremiah Fincher | ||||
| # Copyright (c) 2010, James McCoy | ||||
| # Copyright (c) 2010,2015 James McCoy | ||||
| # All rights reserved. | ||||
| # | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| @ -185,99 +185,10 @@ class Network(callbacks.Plugin): | ||||
|         if (irc, loweredNick) not in self._whois: | ||||
|             return | ||||
|         (replyIrc, replyMsg, d, command) = self._whois[(irc, loweredNick)] | ||||
|         START_CODE = '311' if command == 'whois' else '314' | ||||
|         hostmask = '@'.join(d[START_CODE].args[2:4]) | ||||
|         user = d[START_CODE].args[-1] | ||||
|         if '319' in d: | ||||
|             channels = [] | ||||
|             for msg in d['319']: | ||||
|                 channels.extend(msg.args[-1].split()) | ||||
|             ops = [] | ||||
|             voices = [] | ||||
|             normal = [] | ||||
|             halfops = [] | ||||
|             for channel in channels: | ||||
|                 origchan = channel | ||||
|                 channel = channel.lstrip('@%+~!') | ||||
|                 # UnrealIRCd uses & for user modes and disallows it as a | ||||
|                 # channel-prefix, flying in the face of the RFC.  Have to | ||||
|                 # handle this specially when processing WHOIS response. | ||||
|                 testchan = channel.lstrip('&') | ||||
|                 if testchan != channel and irc.isChannel(testchan): | ||||
|                     channel = testchan | ||||
|                 diff = len(channel) - len(origchan) | ||||
|                 modes = origchan[:diff] | ||||
|                 chan = irc.state.channels.get(channel) | ||||
|                 # The user is in a channel the bot is in, so the ircd may have | ||||
|                 # responded with otherwise private data. | ||||
|                 if chan: | ||||
|                     # Skip channels the caller isn't in.  This prevents | ||||
|                     # us from leaking information when the channel is +s or the | ||||
|                     # target is +i. | ||||
|                     if replyMsg.nick not in chan.users: | ||||
|                         continue | ||||
|                     # Skip +s channels the target is in only if the reply isn't | ||||
|                     # being sent to that channel. | ||||
|                     if 's' in chan.modes and \ | ||||
|                        not ircutils.strEqual(replyMsg.args[0], channel): | ||||
|                         continue | ||||
|                 if not modes: | ||||
|                     normal.append(channel) | ||||
|                 elif utils.iter.any(lambda c: c in modes,('@', '&', '~', '!')): | ||||
|                     ops.append(channel) | ||||
|                 elif utils.iter.any(lambda c: c in modes, ('%',)): | ||||
|                     halfops.append(channel) | ||||
|                 elif utils.iter.any(lambda c: c in modes, ('+',)): | ||||
|                     voices.append(channel) | ||||
|             L = [] | ||||
|             if ops: | ||||
|                 L.append(format(_('is an op on %L'), ops)) | ||||
|             if halfops: | ||||
|                 L.append(format(_('is a halfop on %L'), halfops)) | ||||
|             if voices: | ||||
|                 L.append(format(_('is voiced on %L'), voices)) | ||||
|             if normal: | ||||
|                 if L: | ||||
|                     L.append(format(_('is also on %L'), normal)) | ||||
|                 else: | ||||
|                     L.append(format(_('is on %L'), normal)) | ||||
|         else: | ||||
|             if command == 'whois': | ||||
|                 L = [_('isn\'t on any publicly visible channels')] | ||||
|             else: | ||||
|                 L = [] | ||||
|         channels = format('%L', L) | ||||
|         if '317' in d: | ||||
|             idle = utils.timeElapsed(d['317'].args[2]) | ||||
|             signon = time.strftime(conf.supybot.reply.format.time(), | ||||
|                                    time.localtime(float(d['317'].args[3]))) | ||||
|         else: | ||||
|             idle = _('<unknown>') | ||||
|             signon = _('<unknown>') | ||||
|         if '312' in d: | ||||
|             server = d['312'].args[2] | ||||
|             if len(d['312']) > 3: | ||||
|                 signoff = d['312'].args[3] | ||||
|         else: | ||||
|             server = _('<unknown>') | ||||
|         if '301' in d: | ||||
|             away = ' %s is away: %s.' % (nick, d['301'].args[2]) | ||||
|         else: | ||||
|             away = '' | ||||
|         if '320' in d: | ||||
|             if d['320'].args[2]: | ||||
|                 identify = _(' identified') | ||||
|             else: | ||||
|                 identify = '' | ||||
|         else: | ||||
|             identify = '' | ||||
|         if command == 'whois': | ||||
|             s = _('%s (%s) has been%s on server %s since %s (idle for %s). %s ' | ||||
|                 '%s.%s') % (user, hostmask, identify, server, | ||||
|                         signon, idle, nick, channels, away) | ||||
|         else: | ||||
|             s = _('%s (%s) has been%s on server %s and disconnected on %s.') % \ | ||||
|                     (user, hostmask, identify, server, signoff) | ||||
|         d['318'] = msg | ||||
|         s = ircutils.formatWhois(irc, d, caller=replyMsg.nick, | ||||
|                                  channel=replyMsg.args[0], | ||||
|                                  command=command) | ||||
|         replyIrc.reply(s) | ||||
|         del self._whois[(irc, loweredNick)] | ||||
|     do369 = do318 | ||||
|  | ||||
| @ -279,7 +279,7 @@ class QuoteGrabs(callbacks.Plugin): | ||||
|         # opposed to channel which is used to determine which db to store the | ||||
|         # quote in | ||||
|         chan = msg.args[0] | ||||
|         if chan is None or not ircutils.isChannel(chan): | ||||
|         if chan is None or not irc.isChannel(chan): | ||||
|             raise callbacks.ArgumentError | ||||
|         if ircutils.nickEqual(nick, msg.nick): | ||||
|             irc.error(_('You can\'t quote grab yourself.'), Raise=True) | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| ### | ||||
| # Copyright (c) 2002-2004, Jeremiah Fincher | ||||
| # Copyright (c) 2010, James McCoy | ||||
| # Copyright (c) 2010,2015 James McCoy | ||||
| # All rights reserved. | ||||
| # | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| @ -202,64 +202,9 @@ class Relay(callbacks.Plugin): | ||||
|         if (irc, loweredNick) not in self._whois: | ||||
|             return | ||||
|         (replyIrc, replyMsg, d) = self._whois[(irc, loweredNick)] | ||||
|         hostmask = '@'.join(d['311'].args[2:4]) | ||||
|         user = d['311'].args[-1] | ||||
|         if '319' in d: | ||||
|             channels = d['319'].args[-1].split() | ||||
|             ops = [] | ||||
|             voices = [] | ||||
|             normal = [] | ||||
|             halfops = [] | ||||
|             for channel in channels: | ||||
|                 if channel.startswith('@'): | ||||
|                     ops.append(channel[1:]) | ||||
|                 elif channel.startswith('%'): | ||||
|                     halfops.append(channel[1:]) | ||||
|                 elif channel.startswith('+'): | ||||
|                     voices.append(channel[1:]) | ||||
|                 else: | ||||
|                     normal.append(channel) | ||||
|             L = [] | ||||
|             if ops: | ||||
|                 L.append(format(_('is an op on %L'), ops)) | ||||
|             if halfops: | ||||
|                 L.append(format(_('is a halfop on %L'), halfops)) | ||||
|             if voices: | ||||
|                 L.append(format(_('is voiced on %L'), voices)) | ||||
|             if normal: | ||||
|                 if L: | ||||
|                     L.append(format(_('is also on %L'), normal)) | ||||
|                 else: | ||||
|                     L.append(format(_('is on %L'), normal)) | ||||
|         else: | ||||
|             L = [_('isn\'t on any non-secret channels')] | ||||
|         channels = format('%L', L) | ||||
|         if '317' in d: | ||||
|             idle = utils.timeElapsed(d['317'].args[2]) | ||||
|             signon = time.strftime(conf.supybot.reply.format.time(), | ||||
|                                    time.localtime(float(d['317'].args[3]))) | ||||
|         else: | ||||
|             idle = _('<unknown>') | ||||
|             signon = _('<unknown>') | ||||
|         if '312' in d: | ||||
|             server = d['312'].args[2] | ||||
|         else: | ||||
|             server = _('<unknown>') | ||||
|         if '301' in d: | ||||
|             away = format(_('  %s is away: %s.'), nick, d['301'].args[2]) | ||||
|         else: | ||||
|             away = '' | ||||
|         if '320' in d: | ||||
|             if d['320'].args[2]: | ||||
|                 identify = _(' identified') | ||||
|             else: | ||||
|                 identify = '' | ||||
|         else: | ||||
|             identify = '' | ||||
|         s = format(_('%s (%s) has been%s on server %s since %s (idle for %s) ' | ||||
|                    'and %s.%s'), | ||||
|                    user, hostmask, identify, server, signon, idle, | ||||
|                    channels, away) | ||||
|         d['318'] = msg | ||||
|         s = ircutils.formatWhois(irc, d, caller=replyMsg.nick, | ||||
|                                  channel=replyMsg.args[0]) | ||||
|         replyIrc.reply(s) | ||||
|         del self._whois[(irc, loweredNick)] | ||||
| 
 | ||||
|  | ||||
| @ -71,7 +71,7 @@ conf.registerChannelValue(ShrinkUrl, 'shrinkSnarfer', | ||||
|     shrink snarfer is enabled.  This snarfer will watch for URLs in the | ||||
|     channel, and if they're sufficiently long (as determined by | ||||
|     supybot.plugins.ShrinkUrl.minimumLength) it will post a | ||||
|     smaller URL from tinyurl.com, as denoted in | ||||
|     smaller URL from the service as denoted in | ||||
|     supybot.plugins.ShrinkUrl.default."""))) | ||||
| conf.registerChannelValue(ShrinkUrl.shrinkSnarfer, 'showDomain', | ||||
|     registry.Boolean(True, _("""Determines whether the snarfer will show the | ||||
|  | ||||
| @ -1289,7 +1289,7 @@ class Commands(BasePlugin): | ||||
|             if 'command has no help.' in help: | ||||
|                 # Note: this case will never happen, unless 'checkDoc' is set | ||||
|                 # to False. | ||||
|                 irc.error(_('Invalid arguments for %s.') % ' '.join(command)) | ||||
|                 irc.error(_('Invalid arguments for %s.') % formatCommand(command)) | ||||
|             else: | ||||
|                 irc.reply(help) | ||||
|         except (SyntaxError, Error) as e: | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| ### | ||||
| # Copyright (c) 2002-2005, Jeremiah Fincher | ||||
| # Copyright (c) 2009-2010, James McCoy | ||||
| # Copyright (c) 2009-2010,2015, James McCoy | ||||
| # All rights reserved. | ||||
| # | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| @ -443,8 +443,8 @@ def _getRe(f): | ||||
|                 else: | ||||
|                     state.args.append(s) | ||||
|             else: | ||||
|                 state.errorInvalid(_('regular expression'), s) | ||||
|         except IndexError: | ||||
|                 raise ValueError | ||||
|         except (ValueError, IndexError): | ||||
|             args[:] = original | ||||
|             state.errorInvalid(_('regular expression'), s) | ||||
|     return get | ||||
|  | ||||
| @ -1135,8 +1135,11 @@ class Irc(IrcCommandDispatcher): | ||||
|         if not self.afterConnect: | ||||
|             newNick = self._getNextNick() | ||||
|             assert newNick != self.nick | ||||
|             log.info('Got 433: %s %s.  Trying %s.',self.nick, problem, newNick) | ||||
|             log.info('Got %s: %s %s.  Trying %s.', | ||||
|                      msg.command, self.nick, problem, newNick) | ||||
|             self.sendMsg(ircmsgs.nick(newNick)) | ||||
|     def do437(self, msg): | ||||
|         self.do43x(msg, 'is temporarily unavailable') | ||||
|     def do433(self, msg): | ||||
|         self.do43x(msg, 'is in use') | ||||
|     def do432(self, msg): | ||||
|  | ||||
							
								
								
									
										119
									
								
								src/ircutils.py
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								src/ircutils.py
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| ### | ||||
| # Copyright (c) 2002-2005, Jeremiah Fincher | ||||
| # Copyright (c) 2009,2011, James McCoy | ||||
| # Copyright (c) 2009,2011,2015 James McCoy | ||||
| # All rights reserved. | ||||
| # | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| @ -375,6 +375,123 @@ def stripFormatting(s): | ||||
|     s = stripUnderline(s) | ||||
|     return s.replace('\x0f', '').replace('\x0F', '') | ||||
| 
 | ||||
| _containsFormattingRe = re.compile(r'[\x02\x03\x16\x1f]') | ||||
| def formatWhois(irc, replies, caller='', channel='', command='whois'): | ||||
|     """Returns a string describing the target of a WHOIS command. | ||||
| 
 | ||||
|     Arguments are: | ||||
|     * irc: the irclib.Irc object on which the replies was received | ||||
| 
 | ||||
|     * replies: a dict mapping the reply codes ('311', '312', etc.) to their | ||||
|       corresponding ircmsg.IrcMsg | ||||
| 
 | ||||
|     * caller: an optional nick specifying who requested the whois information | ||||
| 
 | ||||
|     * channel: an optional channel specifying where the reply will be sent | ||||
| 
 | ||||
|     If provided, caller and channel will be used to avoid leaking information | ||||
|     that the caller/channel shouldn't be privy to. | ||||
|     """ | ||||
|     hostmask = '@'.join(replies['311'].args[2:4]) | ||||
|     nick = replies['318'].args[1] | ||||
|     user = replies['311'].args[-1] | ||||
|     (replyIrc, replyMsg, d, command) = self._whois[(irc, loweredNick)] | ||||
|     START_CODE = '311' if command == 'whois' else '314' | ||||
|     hostmask = '@'.join(d[START_CODE].args[2:4]) | ||||
|     user = d[START_CODE].args[-1] | ||||
|     if _containsFormattingRe.search(user) and user[-1] != '\x0f': | ||||
|         # For good measure, disable any formatting | ||||
|         user = '%s\x0f' % user | ||||
|     if '319' in replies: | ||||
|         channels = replies['319'].args[-1].split() | ||||
|         ops = [] | ||||
|         voices = [] | ||||
|         normal = [] | ||||
|         halfops = [] | ||||
|         for chan in channels: | ||||
|             origchan = chan | ||||
|             chan = chan.lstrip('@%+~!') | ||||
|             # UnrealIRCd uses & for user modes and disallows it as a | ||||
|             # channel-prefix, flying in the face of the RFC.  Have to | ||||
|             # handle this specially when processing WHOIS response. | ||||
|             testchan = chan.lstrip('&') | ||||
|             if testchan != chan and irc.isChannel(testchan): | ||||
|                 chan = testchan | ||||
|             diff = len(chan) - len(origchan) | ||||
|             modes = origchan[:diff] | ||||
|             chanState = irc.state.channels.get(chan) | ||||
|             # The user is in a channel the bot is in, so the ircd may have | ||||
|             # responded with otherwise private data. | ||||
|             if chanState: | ||||
|                 # Skip channels the callee isn't in.  This helps prevents | ||||
|                 # us leaking information when the channel is +s or the | ||||
|                 # target is +i | ||||
|                 if caller not in chanState.users: | ||||
|                     continue | ||||
|                 # Skip +s channels the target is in only if the reply isn't | ||||
|                 # being sent to that channel | ||||
|                 if 's' in chanState.modes and \ | ||||
|                    not ircutils.strEqual(channel or '', chan): | ||||
|                     continue | ||||
|             if not modes: | ||||
|                 normal.append(chan) | ||||
|             elif utils.iter.any(lambda c: c in modes,('@', '&', '~', '!')): | ||||
|                 ops.append(chan[1:]) | ||||
|             elif utils.iter.any(lambda c: c in modes, ('%',)): | ||||
|                 halfops.append(chan[1:]) | ||||
|             elif utils.iter.any(lambda c: c in modes, ('+',)): | ||||
|                 voices.append(chan[1:]) | ||||
|         L = [] | ||||
|         if ops: | ||||
|             L.append(format(_('is an op on %L'), ops)) | ||||
|         if halfops: | ||||
|             L.append(format(_('is a halfop on %L'), halfops)) | ||||
|         if voices: | ||||
|             L.append(format(_('is voiced on %L'), voices)) | ||||
|         if normal: | ||||
|             if L: | ||||
|                 L.append(format(_('is also on %L'), normal)) | ||||
|             else: | ||||
|                 L.append(format(_('is on %L'), normal)) | ||||
|     else: | ||||
|         if command == 'whois': | ||||
|             L = [_('isn\'t on any non-secret channels')] | ||||
|         else: | ||||
|             L = [] | ||||
|     channels = format('%L', L) | ||||
|     if '317' in replies: | ||||
|         idle = utils.timeElapsed(replies['317'].args[2]) | ||||
|         signon = utils.str.timestamp(float(replies['317'].args[3])) | ||||
|     else: | ||||
|         idle = '<unknown>' | ||||
|         signon = '<unknown>' | ||||
|     if '312' in replies: | ||||
|         server = replies['312'].args[2] | ||||
|         if len(d['312']) > 3: | ||||
|             signoff = d['312'].args[3] | ||||
|     else: | ||||
|         server = '<unknown>' | ||||
|     if '301' in replies: | ||||
|         away = '  %s is away: %s.' % (nick, replies['301'].args[2]) | ||||
|     else: | ||||
|         away = '' | ||||
|     if '320' in replies: | ||||
|         if replies['320'].args[2]: | ||||
|             identify = ' identified' | ||||
|         else: | ||||
|             identify = '' | ||||
|     else: | ||||
|         identify = '' | ||||
|     if command == 'whois': | ||||
|         s = _('%s (%s) has been%s on server %s since %s (idle for %s) and ' | ||||
|             '%s.%s').decode('utf8') % (user, hostmask, identify, server, | ||||
|                     signon, idle, channels, away) | ||||
|     else: | ||||
|         s = _('%s (%s) has been%s on server %s and disconnect on %s.') \ | ||||
|                 .decode('utf8') % \ | ||||
|                 (user, hostmask, identify, server, signoff) | ||||
|     return s | ||||
| 
 | ||||
| class FormatContext(object): | ||||
|     def __init__(self): | ||||
|         self.reset() | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| ### | ||||
| # Copyright (c) 2002-2005, Jeremiah Fincher | ||||
| # Copyright (c) 2015, James McCoy | ||||
| # All rights reserved. | ||||
| # | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| @ -196,13 +197,24 @@ class FirstTestCase(CommandsTestCase): | ||||
|         self.assertStateErrored([first('int', 'something')], ['words'], | ||||
|                                 errored=False) | ||||
| 
 | ||||
| <<<<<<< HEAD | ||||
| ======= | ||||
|     def testLongRegexp(self): | ||||
|         spec = [first('regexpMatcher', 'regexpReplacer'), 'text'] | ||||
|         self.assertStateErrored(spec, ['s/foo/bar/', 'x' * 512], errored=False) | ||||
| 
 | ||||
| >>>>>>> supybot/master | ||||
| class GetoptTestCase(PluginTestCase): | ||||
|     plugins = ('Misc',) # We put something so it does not complain | ||||
|     class Foo(callbacks.Plugin): | ||||
|         def bar(self, irc, msg, args, optlist): | ||||
|             irc.reply(' '.join(sorted(['%s:%d'%x for x in optlist]))) | ||||
| <<<<<<< HEAD | ||||
|         bar = wrap(bar, [getopts({'foo': 'int', 'fbar': 'int'})], | ||||
|                    checkDoc=False) | ||||
| ======= | ||||
|         bar = wrap(bar, [getopts({'foo': 'int', 'fbar': 'int'})]) | ||||
| >>>>>>> supybot/master | ||||
| 
 | ||||
|     def testGetoptsExact(self): | ||||
|         self.irc.addCallback(self.Foo(self.irc)) | ||||
| @ -211,6 +223,9 @@ class GetoptTestCase(PluginTestCase): | ||||
|         self.assertResponse('bar --f 3 --fb 5', | ||||
|                 'Error: Invalid arguments for bar.') | ||||
| 
 | ||||
| <<<<<<< HEAD | ||||
| 
 | ||||
| ======= | ||||
| >>>>>>> supybot/master | ||||
| # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Valentin Lorentz
						Valentin Lorentz