Use our newly annotated ircmsgs to enhance Misc.last's output.

This commit is contained in:
James Vega 2004-09-10 06:45:27 +00:00
parent eb9bd70599
commit 51ad408ff3
3 changed files with 61 additions and 31 deletions

View File

@ -63,6 +63,11 @@ conf.registerGlobalValue(conf.supybot.plugins.Misc, 'listPrivatePlugins',
plugins with the list command if given the --private switch. If this is plugins with the list command if given the --private switch. If this is
disabled, non-owner users should be unable to see what private plugins disabled, non-owner users should be unable to see what private plugins
are loaded.""")) are loaded."""))
conf.registerGlobalValue(conf.supybot.plugins.Misc, 'timestampFormat',
registry.String('[%H:%M:%S]', """Determines the format string for
timestamps in the Misc.last command. Refer to the Python documentation
for the time module to see what formats are accepted. If you set this
variable to the empty string, the timestamp will not be shown."""))
class Misc(callbacks.Privmsg): class Misc(callbacks.Privmsg):
def __init__(self): def __init__(self):
@ -454,31 +459,38 @@ class Misc(callbacks.Privmsg):
ircutils.isChannel(msg.args[0]) ircutils.isChannel(msg.args[0])
def last(self, irc, msg, args): def last(self, irc, msg, args):
"""[--{from,in,to,with,without,regexp,nolimit}] <args> """[--{from,in,on,with,without,regexp,nolimit}] <args>
Returns the last message matching the given criteria. --from requires Returns the last message matching the given criteria. --from requires
a nick from whom the message came; --in and --to require a channel the a nick from whom the message came; --in requires a channel the message
message was sent to; --with requires some string that had to be in the was sent to; --on requires a netowkr the message was sent on; --with
message; --regexp requires a regular expression the message must i requires some string that had to be in the message; --regexp requires
match; --nolimit returns all the messages that can be found. By a regular expression the message must i match; --nolimit returns all
default, the current channel is searched. the messages that can be found. By default, the current channel is
searched.
""" """
(optlist, rest) = getopt.getopt(args, '', ['from=', 'in=', 'to=', (optlist, rest) = getopt.getopt(args, '', ['from=', 'in=', 'on=',
'with=', 'regexp=', 'with=', 'regexp=',
'without=', 'nolimit']) 'without=', 'nolimit'])
predicates = {} predicates = {}
nolimit = False nolimit = False
if ircutils.isChannel(msg.args[0]): if ircutils.isChannel(msg.args[0]):
predicates['in'] = lambda m: m.args[0] == msg.args[0] predicates['in'] = lambda m: ircutils.strEqual(m.args[0],
msg.args[0])
predicates['on'] = lambda m: m.receivedOn == msg.receivedOn
for (option, arg) in optlist: for (option, arg) in optlist:
if option == '--from': if option == '--from':
def f(m, arg=arg): def f(m, arg=arg):
return ircutils.hostmaskPatternEqual(arg, m.nick) return ircutils.hostmaskPatternEqual(arg, m.nick)
predicates['from'] = f predicates['from'] = f
elif option == '--in' or option == 'to': elif option == '--in':
def f(m, arg=arg): def f(m, arg=arg):
return m.args[0] == arg return ircutils.strEqual(m.args[0], arg)
predicates['in'] = f predicates['in'] = f
elif option == '--on':
def f(m, arg=arg):
return m.receivedOn == arg
predicates['on'] = f
elif option == '--with': elif option == '--with':
def f(m, arg=arg): def f(m, arg=arg):
return arg.lower() in m.args[1].lower() return arg.lower() in m.args[1].lower()
@ -505,15 +517,16 @@ class Misc(callbacks.Privmsg):
iterable.next() # Drop the first message. iterable.next() # Drop the first message.
predicates = list(utils.flatten(predicates.itervalues())) predicates = list(utils.flatten(predicates.itervalues()))
resp = [] resp = []
tsf = self.registryValue('timestampFormat')
for m in iterable: for m in iterable:
for predicate in predicates: for predicate in predicates:
if not predicate(m): if not predicate(m):
break break
else: else:
if nolimit: if nolimit:
resp.append(ircmsgs.prettyPrint(m)) resp.append(ircmsgs.prettyPrint(m, timestampFormat=tsf))
else: else:
irc.reply(ircmsgs.prettyPrint(m)) irc.reply(ircmsgs.prettyPrint(m, timestampFormat=tsf))
return return
if not resp: if not resp:
irc.error('I couldn\'t find a message matching that criteria in ' irc.error('I couldn\'t find a message matching that criteria in '

View File

@ -260,7 +260,7 @@ def toXml(msg, pretty=True, includeTime=True):
L.append('</msg>\n') L.append('</msg>\n')
return ''.join(L) return ''.join(L)
def prettyPrint(msg, addRecipients=False): def prettyPrint(msg, addRecipients=False, timestampFormat=None):
"""Provides a client-friendly string form for messages. """Provides a client-friendly string form for messages.
IIRC, I copied BitchX's (or was it XChat's?) format for messages. IIRC, I copied BitchX's (or was it XChat's?) format for messages.
@ -304,6 +304,9 @@ def prettyPrint(msg, addRecipients=False):
s = '*** %s has quit IRC%s' % (msg.nick, quitmsg) s = '*** %s has quit IRC%s' % (msg.nick, quitmsg)
elif msg.command == 'TOPIC': elif msg.command == 'TOPIC':
s = '*** %s changes topic to %s' % (nickorprefix(), msg.args[1]) s = '*** %s changes topic to %s' % (nickorprefix(), msg.args[1])
at = getattr(msg, 'receivedAt', False)
if timestampFormat and at:
s = '%s %s' % (time.strftime(timestampFormat, time.localtime(at)), s)
return s return s
### ###

View File

@ -32,13 +32,13 @@
from testsupport import * from testsupport import *
class MiscTestCase(ChannelPluginTestCase): class MiscTestCase(ChannelPluginTestCase):
plugins = ('Misc', 'Utilities', 'Gameknot', 'Ctcp', 'Dict', 'User') plugins = ('Misc', 'Utilities', 'Gameknot', 'Anonymous', 'Dict', 'User')
def testAction(self): def testAction(self):
self.assertAction('action moos', 'moos') self.assertAction('action moos', 'moos')
def testActionDoesNotAllowEmptyString(self): def testActionDoesNotAllowEmptyString(self):
self.assertError('action') self.assertHelp('action')
self.assertError('action ""') self.assertHelp('action ""')
def testReplyWhenNotCommand(self): def testReplyWhenNotCommand(self):
try: try:
@ -97,10 +97,13 @@ class MiscTestCase(ChannelPluginTestCase):
# If Ctcp changes to public, these tests will break. So if # If Ctcp changes to public, these tests will break. So if
# the next assert fails, change the plugin we test for public/private # the next assert fails, change the plugin we test for public/private
# to some other non-public plugin. # to some other non-public plugin.
name = 'Ctcp' name = 'Anonymous'
self.failIf(self.irc.getCallback(name).public) conf.supybot.plugins.Anonymous.public.setValue(False)
self.assertNotRegexp('list', name) self.assertNotRegexp('list', name)
self.assertRegexp('list --private', name) self.assertRegexp('list --private', name)
conf.supybot.plugins.Anonymous.public.setValue(True)
self.assertRegexp('list', name)
self.assertNotRegexp('list --private', name)
def testListDoesNotIncludeNonCanonicalName(self): def testListDoesNotIncludeNonCanonicalName(self):
self.assertNotRegexp('list Owner', '_exec') self.assertNotRegexp('list Owner', '_exec')
@ -113,6 +116,8 @@ class MiscTestCase(ChannelPluginTestCase):
if network: if network:
def testVersion(self): def testVersion(self):
print '*** This test should start passing when we have our '\
'threaded issues resolved.'
self.assertNotError('version') self.assertNotError('version')
def testSource(self): def testSource(self):
@ -134,10 +139,14 @@ class MiscTestCase(ChannelPluginTestCase):
self.failIf(ircmsgs.isAction(m)) self.failIf(ircmsgs.isAction(m))
def testLast(self): def testLast(self):
orig = conf.supybot.plugins.Misc.timestampFormat()
try:
conf.supybot.plugins.Misc.timestampFormat.setValue('')
self.feedMsg('foo bar baz') self.feedMsg('foo bar baz')
self.assertResponse('last', '<%s> foo bar baz' % self.nick) self.assertResponse('last', '<%s> foo bar baz' % self.nick)
self.assertRegexp('last', '<%s> @last' % self.nick) self.assertRegexp('last', '<%s> @last' % self.nick)
self.assertResponse('last --with foo', '<%s> foo bar baz' % self.nick) self.assertResponse('last --with foo', '<%s> foo bar baz' % \
self.nick)
self.assertResponse('last --without foo', '<%s> @last' % self.nick) self.assertResponse('last --without foo', '<%s> @last' % self.nick)
self.assertRegexp('last --regexp m/\s+/', 'last --without foo') self.assertRegexp('last --regexp m/\s+/', 'last --without foo')
self.assertResponse('last --regexp m/bar/', self.assertResponse('last --regexp m/bar/',
@ -147,6 +156,11 @@ class MiscTestCase(ChannelPluginTestCase):
self.assertResponse('last --from %s*' % self.nick[0], self.assertResponse('last --from %s*' % self.nick[0],
'<%s> @last --from %s' % '<%s> @last --from %s' %
(self.nick, self.nick.upper())) (self.nick, self.nick.upper()))
conf.supybot.plugins.Misc.timestampFormat.setValue('foo')
self.assertSnarfNoResponse('foo bar baz', 1)
self.assertResponse('last', 'foo <%s> foo bar baz' % self.nick)
finally:
conf.supybot.plugins.Misc.timestampFormat.setValue(orig)
def testMore(self): def testMore(self):
self.assertRegexp('echo %s' % ('abc'*300), 'more') self.assertRegexp('echo %s' % ('abc'*300), 'more')