Merge branch 'ircmsg-channel' into netconf-and-ircmsgs-channel

This commit is contained in:
Valentin Lorentz 2019-08-24 15:39:17 +02:00
commit 9326331c60
11 changed files with 216 additions and 108 deletions

View File

@ -261,7 +261,7 @@ class Owner(callbacks.Plugin):
tokens = callbacks.tokenize(s, channel=msg.args[0])
self.Proxy(irc, msg, tokens)
except SyntaxError as e:
irc.queueMsg(callbacks.error(msg, str(e)))
irc.error(str(e))
def logmark(self, irc, msg, args, text):
"""<text>

View File

@ -156,17 +156,25 @@ def canonicalName(command, preserve_spaces=False):
command = command[:-1]
return ''.join([x for x in command if x not in special]).lower() + reAppend
def reply(msg, s, prefixNick=None, private=None,
def reply(*args, **kwargs):
warnings.warn('callbacks.reply is deprecated. Use irc.reply instead.',
DeprecationWarning)
return _makeReply(dynamic.irc, *args, **kwargs)
def _makeReply(irc, msg, s,
prefixNick=None, private=None,
notice=None, to=None, action=None, error=False,
stripCtcp=True):
msg.tag('repliedTo')
# Ok, let's make the target:
# XXX This isn't entirely right. Consider to=#foo, private=True.
target = ircutils.replyTo(msg)
if ircutils.isChannel(to):
def isPublic(s):
return irc.isChannel(irc._stripChannelPrefix(s))
if to is not None and isPublic(to):
target = to
if ircutils.isChannel(target):
channel = target
if isPublic(target):
channel = irc._stripChannelPrefix(target)
else:
channel = None
if notice is None:
@ -195,11 +203,11 @@ def reply(msg, s, prefixNick=None, private=None,
s = ircutils.safeArgument(s)
if not s and not action:
s = _('Error: I tried to send you an empty message.')
if prefixNick and ircutils.isChannel(target):
if prefixNick and isPublic(target):
# Let's may sure we don't do, "#channel: foo.".
if not ircutils.isChannel(to):
if not isPublic(to):
s = '%s: %s' % (to, s)
if not ircutils.isChannel(target):
if not isPublic(target):
if conf.supybot.reply.withNoticeWhenPrivate():
notice = True
# And now, let's decide whether it's a PRIVMSG or a NOTICE.
@ -214,11 +222,16 @@ def reply(msg, s, prefixNick=None, private=None,
ret.tag('inReplyTo', msg)
return ret
def error(msg, s, **kwargs):
def error(*args, **kwargs):
warnings.warn('callbacks.error is deprecated. Use irc.error instead.',
DeprecationWarning)
return _makeErrorReply(dynamic.irc, *args, **kwargs)
def _makeErrorReply(irc, msg, s, **kwargs):
"""Makes an error reply to msg with the appropriate error payload."""
kwargs['error'] = True
msg.tag('isError')
return reply(msg, s, **kwargs)
return _makeReply(irc, msg, s, **kwargs)
def getHelp(method, name=None, doc=None):
if name is None:
@ -400,8 +413,8 @@ def checkCommandCapability(msg, cb, commandName):
checkCapability(antiCommand)
checkAtEnd = [commandName]
default = conf.supybot.capabilities.default()
if ircutils.isChannel(msg.args[0]):
channel = msg.args[0]
if msg.channel:
channel = msg.channel
checkCapability(ircdb.makeChannelCapability(channel, antiCommand))
chanCommand = ircdb.makeChannelCapability(channel, commandName)
checkAtEnd += [chanCommand]
@ -426,7 +439,7 @@ class RichReplyMethods(object):
return ircutils.standardSubstitute(self, self.msg, s)
def _getConfig(self, wrapper):
return conf.get(wrapper, self.msg.args[0])
return conf.get(wrapper, self.msg.channel)
def replySuccess(self, s='', **kwargs):
v = self._getConfig(conf.supybot.replies.success)
@ -599,7 +612,7 @@ class ReplyIrcProxy(RichReplyMethods):
raise ArgumentError
if msg is None:
msg = self.msg
m = error(msg, s, **kwargs)
m = _makeErrorReply(self, msg, s, **kwargs)
self.irc.queueMsg(m)
return m
@ -609,7 +622,7 @@ class ReplyIrcProxy(RichReplyMethods):
assert not isinstance(s, ircmsgs.IrcMsg), \
'Old code alert: there is no longer a "msg" argument to reply.'
kwargs.pop('noLengthCheck', None)
m = reply(msg, s, **kwargs)
m = _makeReply(self, msg, s, **kwargs)
self.irc.queueMsg(m)
return m
@ -665,9 +678,9 @@ class NestedCommandsIrcProxy(ReplyIrcProxy):
self.notice = None
self.private = None
self.noLengthCheck = None
if self.irc.isChannel(self.msg.args[0]):
if self.msg.channel:
self.prefixNick = conf.get(conf.supybot.reply.withNickPrefix,
self.msg.args[0])
self.msg.channel)
else:
self.prefixNick = conf.supybot.reply.withNickPrefix()
@ -894,7 +907,7 @@ class NestedCommandsIrcProxy(ReplyIrcProxy):
elif self.noLengthCheck:
# noLengthCheck only matters to NestedCommandsIrcProxy, so
# it's not used here. Just in case you were wondering.
m = reply(msg, s, to=self.to,
m = _makeReply(self, msg, s, to=self.to,
notice=self.notice,
action=self.action,
private=self.private,
@ -930,7 +943,7 @@ class NestedCommandsIrcProxy(ReplyIrcProxy):
# action implies noLengthCheck, which has already been
# handled. Let's stick an assert in here just in case.
assert not self.action
m = reply(msg, s, to=self.to,
m = _makeReply(self, msg, s, to=self.to,
notice=self.notice,
private=self.private,
prefixNick=self.prefixNick,
@ -946,7 +959,7 @@ class NestedCommandsIrcProxy(ReplyIrcProxy):
while instant > 1 and msgs:
instant -= 1
response = msgs.pop()
m = reply(msg, response, to=self.to,
m = _makeReply(self, msg, response, to=self.to,
notice=self.notice,
private=self.private,
prefixNick=self.prefixNick,
@ -976,10 +989,10 @@ class NestedCommandsIrcProxy(ReplyIrcProxy):
pass # We'll leave it as it is.
mask = prefix.split('!', 1)[1]
self._mores[mask] = msgs
public = self.irc.isChannel(msg.args[0])
public = bool(self.msg.channel)
private = self.private or not public
self._mores[msg.nick] = (private, msgs)
m = reply(msg, response, to=self.to,
m = _makeReply(self, msg, response, to=self.to,
action=self.action,
notice=self.notice,
private=self.private,
@ -1035,7 +1048,7 @@ class NestedCommandsIrcProxy(ReplyIrcProxy):
if not isinstance(self.irc, irclib.Irc):
return self.irc.error(s, **kwargs)
else:
m = error(self.msg, s, **kwargs)
m = _makeErrorReply(self, self.msg, s, **kwargs)
self.irc.queueMsg(m)
return m
else:
@ -1346,7 +1359,7 @@ class Commands(BasePlugin, SynchronizedAndFirewalled):
help = getHelp
chan = None
if dynamic.msg is not None:
chan = dynamic.msg.args[0]
chan = dynamic.msg.channel
if simpleSyntax is None:
simpleSyntax = conf.get(conf.supybot.reply.showSimpleSyntax, chan)
if simpleSyntax:
@ -1385,7 +1398,7 @@ class PluginMixin(BasePlugin, irclib.IrcCallback):
else:
noIgnore = self.noIgnore
if noIgnore or \
not ircdb.checkIgnored(msg.prefix, msg.args[0]) or \
not ircdb.checkIgnored(msg.prefix, msg.channel) or \
not ircutils.isUserHostmask(msg.prefix): # Some services impl.
self.__parent.__call__(irc, msg)
else:

View File

@ -205,9 +205,12 @@ def urlSnarfer(f):
"""Protects the snarfer from loops (with other bots) and whatnot."""
def newf(self, irc, msg, match, *L, **kwargs):
url = match.group(0)
channel = msg.args[0]
if not irc.isChannel(channel) or (ircmsgs.isCtcp(msg) and not
ircmsgs.isAction(msg)):
channel = msg.channel
if not channel:
# Don't snarf in private
return
if not (ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg)):
# Don't snarf CTCPs unless they are a /me
return
if ircdb.channels.getChannel(channel).lobotomized:
self.log.debug('Not snarfing in %s: lobotomized.', channel)
@ -491,10 +494,11 @@ def getChannel(irc, msg, args, state):
return
if args and irc.isChannel(args[0]):
channel = args.pop(0)
elif irc.isChannel(msg.args[0]):
channel = msg.args[0]
elif msg.channel:
channel = msg.channel
else:
state.log.debug('Raising ArgumentError because there is no channel.')
print(msg.channel, msg)
raise callbacks.ArgumentError
state.channel = channel
state.args.append(channel)
@ -502,8 +506,8 @@ def getChannel(irc, msg, args, state):
def getChannels(irc, msg, args, state):
if args and all(map(irc.isChannel, args[0].split(','))):
channels = args.pop(0).split(',')
elif irc.isChannel(msg.args[0]):
channels = [msg.args[0]]
elif msg.channel:
channels = [msg.channel]
else:
state.log.debug('Raising ArgumentError because there is no channel.')
raise callbacks.ArgumentError
@ -535,11 +539,11 @@ def inChannel(irc, msg, args, state):
state.error(_('I\'m not in %s.') % state.channel, Raise=True)
def onlyInChannel(irc, msg, args, state):
if not (irc.isChannel(msg.args[0]) and msg.args[0] in irc.state.channels):
if not (msg.channel and msg.channel in irc.state.channels):
state.error(_('This command may only be given in a channel that I am '
'in.'), Raise=True)
else:
state.channel = msg.args[0]
state.channel = msg.channel
state.args.append(state.channel)
def callerInGivenChannel(irc, msg, args, state):
@ -576,8 +580,8 @@ def getChannelOrGlobal(irc, msg, args, state):
elif args and irc.isChannel(args[0]):
channel = args.pop(0)
state.channel = channel
elif irc.isChannel(msg.args[0]):
channel = msg.args[0]
elif msg.channel:
channel = msg.channel
state.channel = channel
else:
state.log.debug('Raising ArgumentError because there is no channel.')
@ -620,11 +624,11 @@ def getSomethingNoSpaces(irc, msg, args, state, *L):
getSomething(irc, msg, args, state, p=p, *L)
def private(irc, msg, args, state):
if irc.isChannel(msg.args[0]):
if msg.channel:
state.errorRequiresPrivacy(Raise=True)
def public(irc, msg, args, state, errmsg=None):
if not irc.isChannel(msg.args[0]):
if not msg.channel:
if errmsg is None:
errmsg = _('This message must be sent in a channel.')
state.error(errmsg, Raise=True)

View File

@ -875,16 +875,34 @@ class Irc(IrcCommandDispatcher, log.Firewalled):
else:
return None
_numericErrorCommandRe = re.compile(r'^[45][0-9][0-9]$')
def feedMsg(self, msg):
"""Called by the IrcDriver; feeds a message received."""
def _tagMsg(self, msg):
"""Sets attribute on an incoming IRC message. Will usually only be
called by feedMsg, but may be useful in tests as well."""
msg.tag('receivedBy', self)
msg.tag('receivedOn', self.network)
msg.tag('receivedAt', time.time())
if msg.args and self.isChannel(msg.args[0]):
channel = msg.args[0]
# Check if the message is sent to a channel
if msg.args:
msg.channel = msg.args[0]
if msg.command in ('NOTICE', 'PRIVMSG') and \
not conf.supybot.protocols.irc.strictRfc():
msg.channel = self._stripChannelPrefix(msg.channel)
if not self.isChannel(msg.channel):
msg.channel = None
else:
channel = None
msg.channel = None
def _stripChannelPrefix(self, channel):
statusmsg_chars = self.state.supported.get('statusmsg', '')
return channel.lstrip(statusmsg_chars)
_numericErrorCommandRe = re.compile(r'^[45][0-9][0-9]$')
def feedMsg(self, msg):
"""Called by the IrcDriver; feeds a message received."""
self._tagMsg(msg)
channel = msg.channel
preInFilter = str(msg).rstrip('\r\n')
log.debug('Incoming message (%s): %s', self.network, preInFilter)

View File

@ -116,7 +116,7 @@ class IrcMsg(object):
# On second thought, let's use methods for tagging.
__slots__ = ('args', 'command', 'host', 'nick', 'prefix', 'user',
'_hash', '_str', '_repr', '_len', 'tags', 'reply_env',
'server_tags', 'time')
'server_tags', 'time', 'channel')
def __init__(self, s='', command='', args=(), prefix='', msg=None,
reply_env=None):
assert not (msg and s), 'IrcMsg.__init__ cannot accept both s and msg'

View File

@ -659,7 +659,10 @@ def safeArgument(s):
def replyTo(msg):
"""Returns the appropriate target to send responses to msg."""
if isChannel(msg.args[0]):
if msg.channel:
# if message was sent to +#channel, we want to reply to +#channel;
# or unvoiced channel users will see the bot reply without the
# origin query
return msg.args[0]
else:
return msg.nick
@ -867,10 +870,7 @@ def standardSubstitute(irc, msg, text, env=None):
vars.update(msg.reply_env)
if irc and msg:
if isChannel(msg.args[0]):
channel = msg.args[0]
else:
channel = 'somewhere'
channel = msg.channel or 'somewhere'
def randNick():
if channel != 'somewhere':
L = list(irc.state.channels[channel].users)

View File

@ -175,6 +175,7 @@ class FunctionsTestCase(SupyTestCase):
self.assertEqual('foobar--', callbacks.canonicalName('foobar--'))
def testAddressed(self):
irc = getTestIrc()
oldprefixchars = str(conf.supybot.reply.whenAddressedBy.chars)
nick = 'supybot'
conf.supybot.reply.whenAddressedBy.chars.set('~!@')
@ -189,6 +190,7 @@ class FunctionsTestCase(SupyTestCase):
for msg in inChannel:
self.assertEqual('foo', callbacks.addressed(nick, msg), msg)
msg = ircmsgs.privmsg(nick, 'foo')
irc._tagMsg(msg)
self.assertEqual('foo', callbacks.addressed(nick, msg))
conf.supybot.reply.whenAddressedBy.chars.set(oldprefixchars)
msg = ircmsgs.privmsg('#foo', '%s::::: bar' % nick)
@ -216,52 +218,84 @@ class FunctionsTestCase(SupyTestCase):
conf.supybot.reply.whenNotAddressed.setValue(original)
def testAddressedWithMultipleNicks(self):
irc = getTestIrc()
msg = ircmsgs.privmsg('#foo', 'bar: baz')
irc._tagMsg(msg)
self.assertEqual(callbacks.addressed('bar', msg), 'baz')
# need to recreate the msg objects since the old ones have already
# been tagged
msg = ircmsgs.privmsg('#foo', 'bar: baz')
irc._tagMsg(msg)
self.assertEqual(callbacks.addressed('biff', msg, nicks=['bar']),
'baz')
def testAddressedWithNickAtEnd(self):
irc = getTestIrc()
msg = ircmsgs.privmsg('#foo', 'baz, bar')
irc._tagMsg(msg)
self.assertEqual(callbacks.addressed('bar', msg,
whenAddressedByNickAtEnd=True),
'baz')
def testAddressedPrefixCharsTakePrecedenceOverNickAtEnd(self):
irc = getTestIrc()
msg = ircmsgs.privmsg('#foo', '@echo foo')
irc._tagMsg(msg)
self.assertEqual(callbacks.addressed('foo', msg,
whenAddressedByNickAtEnd=True,
prefixChars='@'),
'echo foo')
def testReply(self):
irc = getTestIrc()
prefix = 'foo!bar@baz'
channelMsg = ircmsgs.privmsg('#foo', 'bar baz', prefix=prefix)
nonChannelMsg = ircmsgs.privmsg('supybot', 'bar baz', prefix=prefix)
irc._tagMsg(channelMsg)
irc._tagMsg(nonChannelMsg)
self.assertEqual(ircmsgs.notice(nonChannelMsg.nick, 'foo'),
callbacks.reply(channelMsg, 'foo', private=True))
callbacks._makeReply(irc, channelMsg, 'foo',
private=True))
self.assertEqual(ircmsgs.notice(nonChannelMsg.nick, 'foo'),
callbacks.reply(nonChannelMsg, 'foo'))
callbacks._makeReply(irc, nonChannelMsg, 'foo'))
self.assertEqual(ircmsgs.privmsg(channelMsg.args[0],
'%s: foo' % channelMsg.nick),
callbacks.reply(channelMsg, 'foo'))
callbacks._makeReply(irc, channelMsg, 'foo'))
self.assertEqual(ircmsgs.privmsg(channelMsg.args[0],
'foo'),
callbacks.reply(channelMsg, 'foo', prefixNick=False))
callbacks._makeReply(irc, channelMsg, 'foo',
prefixNick=False))
self.assertEqual(ircmsgs.notice(nonChannelMsg.nick, 'foo'),
callbacks.reply(channelMsg, 'foo',
callbacks._makeReply(irc, channelMsg, 'foo',
notice=True, private=True))
def testReplyStatusmsg(self):
irc = getTestIrc()
prefix = 'foo!bar@baz'
msg = ircmsgs.privmsg('+#foo', 'bar baz', prefix=prefix)
irc._tagMsg(msg)
# No statusmsg set, so understood as being a private message, so
# private reply
self.assertEqual(ircmsgs.notice(msg.nick, 'foo'),
callbacks._makeReply(irc, msg, 'foo'))
irc.state.supported['statusmsg'] = '+'
msg = ircmsgs.privmsg('+#foo', 'bar baz', prefix=prefix)
irc._tagMsg(msg)
print(msg.channel)
self.assertEqual(ircmsgs.privmsg('+#foo', '%s: foo' % msg.nick),
callbacks._makeReply(irc, msg, 'foo'))
def testReplyTo(self):
irc = getTestIrc()
prefix = 'foo!bar@baz'
msg = ircmsgs.privmsg('#foo', 'bar baz', prefix=prefix)
self.assertEqual(callbacks.reply(msg, 'blah', to='blah'),
irc._tagMsg(msg)
self.assertEqual(callbacks._makeReply(irc, msg, 'blah', to='blah'),
ircmsgs.privmsg('#foo', 'blah: blah'))
self.assertEqual(callbacks.reply(msg, 'blah', to='blah', private=True),
self.assertEqual(callbacks._makeReply(irc, msg, 'blah', to='blah',
private=True),
ircmsgs.notice('blah', 'blah'))
def testTokenize(self):
@ -682,7 +716,9 @@ class WithPrivateNoticeTestCase(ChannelPluginTestCase):
class ProxyTestCase(SupyTestCase):
def testHashing(self):
irc = getTestIrc()
msg = ircmsgs.ping('0')
irc._tagMsg(msg)
irc = irclib.Irc('test')
proxy = callbacks.SimpleProxy(irc, msg)
# First one way...

View File

@ -47,6 +47,7 @@ class CommandsTestCase(SupyTestCase):
realIrc = getTestIrc()
realIrc.nick = 'test'
realIrc.state.supported['chantypes'] = '#'
realIrc._tagMsg(msg)
irc = callbacks.SimpleProxy(realIrc, msg)
myspec = Spec(spec, **kwargs)
state = myspec(irc, msg, given)

View File

@ -470,6 +470,42 @@ class IrcTestCase(SupyTestCase):
self.irc.feedMsg(msg2)
self.assertEqual(list(self.irc.state.history), [msg1, msg2])
def testMsgChannel(self):
self.irc.reset()
self.irc.state.supported['statusmsg'] = '@'
self.irc.feedMsg(ircmsgs.IrcMsg('PRIVMSG #linux :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, '#linux')
self.irc.feedMsg(ircmsgs.IrcMsg('PRIVMSG @#linux2 :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, '#linux2')
self.irc.feedMsg(ircmsgs.IrcMsg('PRIVMSG +#linux3 :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, None)
self.irc.state.supported['statusmsg'] = '+@'
self.irc.feedMsg(ircmsgs.IrcMsg('PRIVMSG #linux :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, '#linux')
self.irc.feedMsg(ircmsgs.IrcMsg('PRIVMSG @#linux2 :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, '#linux2')
self.irc.feedMsg(ircmsgs.IrcMsg('PRIVMSG +#linux3 :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, '#linux3')
del self.irc.state.supported['statusmsg']
self.irc.feedMsg(ircmsgs.IrcMsg('PRIVMSG #linux :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, '#linux')
self.irc.feedMsg(ircmsgs.IrcMsg('PRIVMSG @#linux2 :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, None)
self.irc.feedMsg(ircmsgs.IrcMsg('PRIVMSG +#linux3 :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, None)
# Test msg.channel is set only for PRIVMSG and NOTICE
self.irc.state.supported['statusmsg'] = '+@'
self.irc.feedMsg(ircmsgs.IrcMsg('NOTICE @#linux :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, '#linux')
self.irc.feedMsg(ircmsgs.IrcMsg('NOTICE @#linux2 :foo bar baz!'))
self.assertEqual(self.irc.state.history[-1].channel, '#linux2')
self.irc.feedMsg(ircmsgs.IrcMsg('MODE @#linux3 +v foo'))
self.assertEqual(self.irc.state.history[-1].channel, None)
def testQuit(self):
self.irc.reset()
self.irc.feedMsg(ircmsgs.IrcMsg(':someuser JOIN #foo'))

View File

@ -281,12 +281,10 @@ class FunctionsTestCase(SupyTestCase):
def testStandardSubstitute(self):
# Stub out random msg and irc objects that provide what
# standardSubstitute wants
msg = ircmsgs.IrcMsg(':%s PRIVMSG #channel :stuff' % self.hostmask)
class Irc(object):
nick = 'bob'
network = 'testnet'
irc = getTestIrc()
irc = Irc()
msg = ircmsgs.IrcMsg(':%s PRIVMSG #channel :stuff' % self.hostmask)
irc._tagMsg(msg)
f = ircutils.standardSubstitute
vars = {'foo': 'bar', 'b': 'c', 'i': 100,
@ -344,9 +342,12 @@ class FunctionsTestCase(SupyTestCase):
self.assertEqual('{}|^', ircutils.toLower('[]\\~'))
def testReplyTo(self):
irc = getTestIrc()
prefix = 'foo!bar@baz'
channel = ircmsgs.privmsg('#foo', 'bar baz', prefix=prefix)
private = ircmsgs.privmsg('jemfinch', 'bar baz', prefix=prefix)
irc._tagMsg(channel)
irc._tagMsg(private)
self.assertEqual(ircutils.replyTo(channel), channel.args[0])
self.assertEqual(ircutils.replyTo(private), private.nick)

View File

@ -37,54 +37,53 @@ class holder:
users = set(map(str, range(1000)))
class FunctionsTestCase(SupyTestCase):
class irc:
class state:
channels = {'#foo': holder()}
nick = 'foobar'
network = 'testnet'
@retry()
def testStandardSubstitute(self):
irc = getTestIrc()
irc.state.channels = {'#foo': holder()}
f = ircutils.standardSubstitute
msg = ircmsgs.privmsg('#foo', 'filler', prefix='biff!quux@xyzzy')
s = f(self.irc, msg, '$rand')
irc._tagMsg(msg)
s = f(irc, msg, '$rand')
try:
int(s)
except ValueError:
self.fail('$rand wasn\'t an int.')
s = f(self.irc, msg, '$randomInt')
s = f(irc, msg, '$randomInt')
try:
int(s)
except ValueError:
self.fail('$randomint wasn\'t an int.')
self.assertEqual(f(self.irc, msg, '$botnick'), self.irc.nick)
self.assertEqual(f(self.irc, msg, '$who'), msg.nick)
self.assertEqual(f(self.irc, msg, '$WHO'),
self.assertEqual(f(irc, msg, '$botnick'), irc.nick)
self.assertEqual(f(irc, msg, '$who'), msg.nick)
self.assertEqual(f(irc, msg, '$WHO'),
msg.nick, 'stand. sub. not case-insensitive.')
self.assertEqual(f(self.irc, msg, '$nick'), msg.nick)
self.assertNotEqual(f(self.irc, msg, '$randomdate'), '$randomdate')
q = f(self.irc,msg,'$randomdate\t$randomdate')
self.assertEqual(f(irc, msg, '$nick'), msg.nick)
self.assertNotEqual(f(irc, msg, '$randomdate'), '$randomdate')
q = f(irc,msg,'$randomdate\t$randomdate')
dl = q.split('\t')
if dl[0] == dl[1]:
self.fail ('Two $randomdates in the same string were the same')
q = f(self.irc, msg, '$randomint\t$randomint')
q = f(irc, msg, '$randomint\t$randomint')
dl = q.split('\t')
if dl[0] == dl[1]:
self.fail ('Two $randomints in the same string were the same')
self.assertNotEqual(f(self.irc, msg, '$today'), '$today')
self.assertNotEqual(f(self.irc, msg, '$now'), '$now')
n = f(self.irc, msg, '$randnick')
self.failUnless(n in self.irc.state.channels['#foo'].users)
n = f(self.irc, msg, '$randomnick')
self.failUnless(n in self.irc.state.channels['#foo'].users)
n = f(self.irc, msg, '$randomnick '*100)
self.assertNotEqual(f(irc, msg, '$today'), '$today')
self.assertNotEqual(f(irc, msg, '$now'), '$now')
n = f(irc, msg, '$randnick')
self.failUnless(n in irc.state.channels['#foo'].users)
n = f(irc, msg, '$randomnick')
self.failUnless(n in irc.state.channels['#foo'].users)
n = f(irc, msg, '$randomnick '*100)
L = n.split()
self.failIf(all(L[0].__eq__, L), 'all $randomnicks were the same')
c = f(self.irc, msg, '$channel')
c = f(irc, msg, '$channel')
self.assertEqual(c, msg.args[0])
net = f(self.irc, msg, '$network')
self.assertEqual(net, self.irc.network)
net = f(irc, msg, '$network')
self.assertEqual(net, irc.network)