Refactored callbacks.{error,reply} and its friends; added supybot.reply.errorWithNotice.

This commit is contained in:
Jeremy Fincher 2004-04-09 02:55:03 +00:00
parent 47d7f5e18b
commit 7f6040a160
3 changed files with 81 additions and 64 deletions

View File

@ -111,29 +111,42 @@ def canonicalName(command):
command = command[:-1] command = command[:-1]
return command.translate(string.ascii, special).lower() + reAppend return command.translate(string.ascii, special).lower() + reAppend
def reply(msg, s, prefixName=True, private=False, notice=False, to=None): def reply(msg, s, prefixName=True, private=False,
"""Makes a reply to msg with the payload s""" notice=False, to=None, action=False):
# Ok, let's make the target:
target = ircutils.replyTo(msg)
if private:
if to is not None:
target = to
else:
target = msg.nick
if to is None:
to = msg.nick
# Ok, now let's make the payload:
s = ircutils.safeArgument(s) s = ircutils.safeArgument(s)
to = to or msg.nick if not s:
if ircutils.isChannel(msg.args[0]) and not private: s = 'Error: I tried to send you an empty message.'
if notice or conf.supybot.reply.withPrivateNotice(): if prefixName and ircutils.isChannel(target):
m = ircmsgs.notice(to, s) s = '%s: %s' % (to, s)
elif prefixName: # And now, let's decide whether it's a PRIVMSG or a NOTICE.
m = ircmsgs.privmsg(msg.args[0], '%s: %s' % (to, s)) msgmaker = ircmsgs.privmsg
else: if notice:
m = ircmsgs.privmsg(msg.args[0], s) msgmaker = ircmsgs.notice
else: if conf.supybot.reply.withPrivateNotice():
if s: target = msg.nick
m = ircmsgs.privmsg(to, s) msgmaker = ircmsgs.notice
else: if action:
return error(msg, 'I tried to send you an empty message.', msgmaker = ircmsgs.action
prefixName=prefixName, private=private, # Finally, we'll return the actual message.
notice=notice, to=to) return msgmaker(target, s)
return m
def error(msg, s, **kwargs): def error(msg, s, private=None, notice=None, **kwargs):
"""Makes an error reply to msg with the appropriate error payload.""" """Makes an error reply to msg with the appropriate error payload."""
return reply(msg, 'Error: ' + s, **kwargs) 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)
def getHelp(method, name=None): def getHelp(method, name=None):
if name is None: if name is None:
@ -548,22 +561,18 @@ class IrcObjectProxy(RichReplyMethods):
self.notice = notice or self.notice self.notice = notice or self.notice
self.private = private or self.private self.private = private or self.private
self.to = to or self.to self.to = to or self.to
self.prefixName = prefixName and self.prefixName self.prefixName = prefixName and self.prefixName and not self.action
self.noLengthCheck = noLengthCheck or self.noLengthCheck # action=True should imply noLengthCheck=True. We can't more actions.
self.noLengthCheck=noLengthCheck or self.noLengthCheck or self.action
if self.finalEvaled: if self.finalEvaled:
if isinstance(self.irc, self.__class__): if not isinstance(self.irc, irclib.Irc):
self.irc.reply(s, self.noLengthCheck, self.prefixName, self.irc.reply(s, private=self.private, notice=self.notice,
self.action, self.private, self.notice, self.to) to=self.to, noLengthCheck=self.noLengthCheck,
prefixName=self.prefixName, action=self.action)
elif self.noLengthCheck: elif self.noLengthCheck:
self.irc.queueMsg(reply(msg, s, self.prefixName, self.irc.queueMsg(reply(msg, s, prefixName=self.prefixName,
self.private, self.notice, self.to)) private=self.private, to=self.to,
elif self.action: action=self.action,notice=self.notice))
target = ircutils.replyTo(msg)
if self.to:
target = self.to
elif self.private:
target = msg.nick
self.irc.queueMsg(ircmsgs.action(target, s))
else: else:
s = ircutils.safeArgument(s) s = ircutils.safeArgument(s)
allowedLength = 450 - len(self.irc.prefix) allowedLength = 450 - len(self.irc.prefix)
@ -587,33 +596,29 @@ class IrcObjectProxy(RichReplyMethods):
response = '%s %s' % (response, n) response = '%s %s' % (response, n)
prefix = msg.prefix prefix = msg.prefix
if self.to and ircutils.isNick(self.to): if self.to and ircutils.isNick(self.to):
### TODO: catch this KeyError. try:
prefix = self.getRealIrc().state.nickToHostmask(self.to) prefix=self.getRealIrc().state.nickToHostmask(self.to)
except KeyError:
pass # We'll leave it as it is.
mask = prefix.split('!', 1)[1] mask = prefix.split('!', 1)[1]
Privmsg._mores[mask] = msgs Privmsg._mores[mask] = msgs
private = self.private or not ircutils.isChannel(msg.args[0]) private = self.private or not ircutils.isChannel(msg.args[0])
Privmsg._mores[msg.nick] = (private, msgs) Privmsg._mores[msg.nick] = (private, msgs)
self.irc.queueMsg(reply(msg, response, self.prefixName, self.irc.queueMsg(reply(msg, response,
self.private, self.notice, self.to)) prefixName=self.prefixName,
private=self.private, to=self.to,
action=self.action,notice=self.notice))
self.finished = True self.finished = True
else: else:
self.args[self.counter] = s self.args[self.counter] = s
self.evalArgs() self.evalArgs()
def error(self, s, private=False): def error(self, s, private=None, notice=None, **kwargs):
"""error(text) -> replies to msg with an error message of text. if not isinstance(self.irc, irclib.Irc):
Keyword arguments:
private=False: True if the error should be given in private.
"""
if isinstance(self.irc, self.__class__):
self.irc.error(s, private) self.irc.error(s, private)
else: else:
s = 'Error: ' + s self.irc.queueMsg(error(self.msg, s, private=private,
if private or conf.supybot.reply.errorInPrivate(): notice=notice, **kwargs))
self.irc.queueMsg(ircmsgs.privmsg(self.msg.nick, s))
else:
self.irc.queueMsg(reply(self.msg, s))
self.finished = True self.finished = True
def getRealIrc(self): def getRealIrc(self):
@ -769,21 +774,14 @@ class IrcObjectProxyRegexp(RichReplyMethods):
self.irc = irc self.irc = irc
self.msg = msg self.msg = msg
def error(self, s, **kwargs): def error(self, s, private=None, notice=None, **kwargs):
self.reply('Error: ' + s, **kwargs) self.irc.queueMsg(error(self.msg, s, private=private,
notice=notice, **kwargs))
def reply(self, s, action=False, to=None, private=False, **kwargs): def reply(self, s, **kwargs):
assert not isinstance(s, ircmsgs.IrcMsg), \ assert not isinstance(s, ircmsgs.IrcMsg), \
'Old code alert: there is no longer a "msg" argument to reply.' 'Old code alert: there is no longer a "msg" argument to reply.'
if action: self.irc.queueMsg(reply(self.msg, s, **kwargs))
target = ircutils.replyTo(self.msg)
if to:
target = to
elif private:
target = msg.nick
self.irc.queueMsg(ircmsgs.action(target, s))
else:
self.irc.queueMsg(reply(self.msg,s,to=to,private=private,**kwargs))
def __getattr__(self, attr): def __getattr__(self, attr):
return getattr(self.irc, attr) return getattr(self.irc, attr)

View File

@ -229,7 +229,16 @@ whether error messages that result from bugs in the bot will show a detailed
error message (the uncaught exception) or a generic error message.""")) error message (the uncaught exception) or a generic error message."""))
supybot.reply.register('errorInPrivate', registry.Boolean(False, """ supybot.reply.register('errorInPrivate', registry.Boolean(False, """
Determines whether the bot will send error messages to users in private.""")) Determines whether the bot will send error messages to users in private. You
might want to do this in order to keep channel traffic to minimum. This can
be used in combination with supybot.reply.errorWithNotice."""))
supybot.reply.register('errorWithNotice', registry.Boolean(False, """
Determines whether the bot will send error messages to users via NOTICE instead
of PRIVMSG. You might want to do this so users can ignore NOTICEs from the bot
and not have to see error messages; or you might want to use it in combination
with supybot.reply.errorInPrivate so private errors don't open a query window
in most IRC clients."""))
supybot.reply.register('noCapabilityError', registry.Boolean(False, """ supybot.reply.register('noCapabilityError', registry.Boolean(False, """
Determines whether the bot will send an error message to users who attempt to Determines whether the bot will send an error message to users who attempt to

View File

@ -200,7 +200,8 @@ class FunctionsTestCase(SupyTestCase):
'foo'), 'foo'),
callbacks.reply(channelMsg, 'foo', prefixName=False)) callbacks.reply(channelMsg, 'foo', prefixName=False))
self.assertEqual(ircmsgs.notice(nonChannelMsg.nick, 'foo'), self.assertEqual(ircmsgs.notice(nonChannelMsg.nick, 'foo'),
callbacks.reply(channelMsg, 'foo', notice=True)) callbacks.reply(channelMsg, 'foo',
notice=True, private=True))
def testReplyTo(self): def testReplyTo(self):
prefix = 'foo!bar@baz' prefix = 'foo!bar@baz'
@ -265,6 +266,15 @@ class PrivmsgTestCase(ChannelPluginTestCase):
finally: finally:
conf.supybot.reply.errorInPrivate.setValue(original) conf.supybot.reply.errorInPrivate.setValue(original)
def testErrorWithNotice(self):
try:
original = conf.supybot.reply.errorWithNotice()
conf.supybot.reply.errorWithNotice.setValue(True)
m = self.getMsg("eval irc.error('foo')")
self.failUnless(m.command == 'NOTICE')
finally:
conf.supybot.reply.errorWithNotice.setValue(original)
def testErrorReplyPrivate(self): def testErrorReplyPrivate(self):
try: try:
original = str(conf.supybot.reply.errorInPrivate) original = str(conf.supybot.reply.errorInPrivate)