diff --git a/src/callbacks.py b/src/callbacks.py index 38fba8e8a..a369257d3 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -124,13 +124,26 @@ def canonicalName(command): return command.translate(string.ascii, special).lower() + reAppend def reply(msg, s, prefixName=True, private=None, - notice=None, to=None, action=None): + notice=None, to=None, action=None, error=False): # Ok, let's make the target: target = ircutils.replyTo(msg) + def getConfig(wrapper): + if ircutils.isChannel(target): + return wrapper.get(target)() + else: + return wrapper() + if ircutils.isChannel(target): + channel = target + else: + channel = None if notice is None: - notice = conf.supybot.reply.withNotice() + notice = getConfig(conf.supybot.reply.withNotice) if private is None: - private = conf.supybot.reply.inPrivate() + private = getConfig(conf.supybot.reply.inPrivate) + if error: + notice = getConfig(conf.supybot.reply.errorWithNotice) or notice + private = getConfig(conf.supybot.reply.errorInPrivate) or private + s = 'Error: ' + s if private: prefixName = False if to is None: @@ -158,13 +171,10 @@ def reply(msg, s, prefixName=True, private=None, # Finally, we'll return the actual message. return msgmaker(target, s) -def error(msg, s, private=None, notice=None, **kwargs): +def error(msg, s, **kwargs): """Makes an error reply to msg with the appropriate error payload.""" - if notice is None: - notice = conf.supybot.reply.errorWithNotice() - if private is None: - private = conf.supybot.reply.errorInPrivate() - return reply(msg, 'Error: ' + s, private=private, notice=notice, **kwargs) + kwargs['error'] = True + return reply(msg, s, **kwargs) def getHelp(method, name=None): if name is None: @@ -693,10 +703,11 @@ class IrcObjectProxy(RichReplyMethods): else: self.irc.queueMsg(error(self.msg, s, **kwargs)) else: - # No argument, let's raise ArgumentError. if self.commandMethod is not None: # We can recurse here because it only gets called once. self.error(formatArgumentError(self.commandMethod), **kwargs) + else: + raise ArgumentError # We shouldn't get here, but just in case. self.finished = True def getRealIrc(self): diff --git a/src/conf.py b/src/conf.py index 9163e934b..327fbcd3d 100644 --- a/src/conf.py +++ b/src/conf.py @@ -89,10 +89,12 @@ def registerGroup(Group, name, group=None): return Group.register(name, group) def registerGlobalValue(group, name, value): + value.channelValue = False return group.register(name, value) def registerChannelValue(group, name, value): value.supplyDefault = True + value.channelValue = True return group.register(name, value) def registerPlugin(name, currentValue=None, public=True): @@ -246,7 +248,10 @@ registerChannelValue(supybot, 'prefixChars', class DefaultCapabilities(registry.SpaceSeparatedListOfStrings): List = ircutils.IrcSet - def setValue(self, v): + # We use a keyword argument trick here to prevent eval'ing of code that + # changes allowDefaultOwner from affecting this. It's not perfect, but + # it's still an improvement, raising the bar for potential crackers. + def setValue(self, v, allowDefaultOwner=allowDefaultOwner): registry.SpaceSeparatedListOfStrings.setValue(self, v) if '-owner' not in self.value and not allowDefaultOwner: print '*** You must run supybot with the --allow-default-owner' @@ -348,11 +353,14 @@ registerChannelValue(supybot.reply, 'noCapabilityError', users to understand the underlying security system preventing them from running certain commands.""")) -registerChannelValue(supybot.reply, 'withPrivateNotice', +registerChannelValue(supybot.reply, 'inPrivate', + registry.Boolean(False, """Determines whether the bot will reply privately + when replying in a channel, rather than replying to the whole channel.""")) + +registerChannelValue(supybot.reply, 'withNotice', registry.Boolean(False, """Determines whether the bot will reply with a - private notice to users rather than sending a message to a channel. - Private notices are particularly nice because they don't generally cause - IRC clients to open a new query window.""")) + notice when replying in a channel, rather than replying with a privmsg as + normal.""")) # XXX: User value. registerGlobalValue(supybot.reply, 'withNoticeWhenPrivate', diff --git a/test/test_callbacks.py b/test/test_callbacks.py index caa64a88b..391cd3df6 100644 --- a/test/test_callbacks.py +++ b/test/test_callbacks.py @@ -256,7 +256,7 @@ class PrivmsgTestCase(ChannelPluginTestCase): def testErrorPrivateKwarg(self): try: original = conf.supybot.reply.errorInPrivate() - conf.supybot.reply.errorInPrivate.set('False') + conf.supybot.reply.errorInPrivate.setValue(False) m = self.getMsg("eval irc.error('foo', private=True)") self.failIf(ircutils.isChannel(m.args[0])) finally: