Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix RFC-compliance of privmsgs/notices/kicks/whois/... with list of n…

…icks/channels are argument. Closes GH-462.
  • Loading branch information...
commit 574d73c14e177ce03cf9093a038c89fe1c45ecd0 1 parent 5209cbc
@ProgVal authored
Showing with 44 additions and 7 deletions.
  1. +12 −7 src/ircmsgs.py
  2. +20 −0 src/ircutils.py
  3. +12 −0 test/test_ircmsgs.py
View
19 src/ircmsgs.py
@@ -337,7 +337,10 @@ def nick():
###
isNick = ircutils.isNick
+areNicks = ircutils.areNicks
isChannel = ircutils.isChannel
+areChannels = ircutils.areChannels
+areReceivers = ircutils.areReceivers
isUserHostmask = ircutils.isUserHostmask
def pong(payload, prefix='', msg=None):
@@ -545,12 +548,14 @@ def kick(channel, nick, s='', prefix='', msg=None):
return IrcMsg(prefix=prefix, command='KICK',
args=(channel, nick), msg=msg)
-def kicks(channel, nicks, s='', prefix='', msg=None):
+def kicks(channels, nicks, s='', prefix='', msg=None):
"""Returns a KICK to kick each of nicks from channel with the message msg.
"""
+ if isinstance(channels, str): # Backward compatibility
+ channels = [channels]
if conf.supybot.protocols.irc.strictRfc():
- assert isChannel(channel), repr(channel)
- assert all(isNick, nicks), nicks
+ assert areChannels(channels), repr(channel)
+ assert areNicks(nicks), repr(nicks)
if msg and not prefix:
prefix = msg.prefix
if sys.version_info[0] < 3 and isinstance(s, unicode):
@@ -566,7 +571,7 @@ def kicks(channel, nicks, s='', prefix='', msg=None):
def privmsg(recipient, s, prefix='', msg=None):
"""Returns a PRIVMSG to recipient with the message msg."""
if conf.supybot.protocols.irc.strictRfc():
- assert (isChannel(recipient) or isNick(recipient)), repr(recipient)
+ assert (areReceivers(recipient)), repr(recipient)
assert s, 's must not be empty.'
if sys.version_info[0] < 3 and isinstance(s, unicode):
s = s.encode('utf8')
@@ -598,7 +603,7 @@ def action(recipient, s, prefix='', msg=None):
def notice(recipient, s, prefix='', msg=None):
"""Returns a NOTICE to recipient with the message msg."""
if conf.supybot.protocols.irc.strictRfc():
- assert (isChannel(recipient) or isNick(recipient)), repr(recipient)
+ assert areReceivers(recipient), repr(recipient)
assert s, 'msg must not be empty.'
if sys.version_info[0] < 3 and isinstance(s, unicode):
s = s.encode('utf8')
@@ -735,7 +740,7 @@ def who(hostmaskOrChannel, prefix='', msg=None):
def whois(nick, mask='', prefix='', msg=None):
"""Returns a WHOIS for nick."""
if conf.supybot.protocols.irc.strictRfc():
- assert isNick(nick), repr(nick)
+ assert areNicks(nick), repr(nick)
if msg and not prefix:
prefix = msg.prefix
args = (nick,)
@@ -745,7 +750,7 @@ def whois(nick, mask='', prefix='', msg=None):
def names(channel=None, prefix='', msg=None):
if conf.supybot.protocols.irc.strictRfc():
- assert isChannel(channel)
+ assert areChannels(channel)
if msg and not prefix:
prefix = msg.prefix
if channel is not None:
View
20 src/ircutils.py
@@ -43,6 +43,7 @@
import random
import string
import textwrap
+import functools
from cStringIO import StringIO as sio
import supybot.utils as utils
@@ -132,6 +133,11 @@ def isNick(s, strictRfc=True, nicklen=None):
not isUserHostmask(s) and \
not ' ' in s and not '!' in s
+def areNicks(s, strictRfc=True, nicklen=None):
+ """Like 'isNick(x)' but for comma-separated list."""
+ nick = functools.partial(isNick, strictRfc=strictRfc, nicklen=nicklen)
+ return all(map(nick, s.split(',')))
+
def isChannel(s, chantypes='#&+!', channellen=50):
"""s => bool
Returns True if s is a valid IRC channel name."""
@@ -142,6 +148,20 @@ def isChannel(s, chantypes='#&+!', channellen=50):
len(s) <= channellen and \
len(s.split(None, 1)) == 1
+def areChannels(s, chantypes='#&+!',channellen=50):
+ """Like 'isChannel(x)' but for comma-separated list."""
+ chan = functools.partial(isChannel, chantypes=chantypes,
+ channellen=channellen)
+ return all(map(chan, s.split(',')))
+
+def areReceivers(s, strictRfc=True, nicklen=None, chantypes='#&+!',
+ channellen=50):
+ """Like 'isNick(x) or isChannel(x)' but for comma-separated list."""
+ nick = functools.partial(isNick, strictRfc=strictRfc, nicklen=nicklen)
+ chan = functools.partial(isChannel, chantypes=chantypes,
+ channellen=channellen)
+ return all(map(lambda x:nick(x) or chan(x), s.split(',')))
+
_patternCache = utils.structures.CacheDict(1000)
def _hostmaskPatternEqual(pattern, hostmask):
try:
View
12 test/test_ircmsgs.py
@@ -161,6 +161,18 @@ def testUnAction(self):
msg = ircmsgs.action('#foo', s)
self.assertEqual(ircmsgs.unAction(msg), s)
+ def testPrivmsg(self):
+ self.assertEqual(str(ircmsgs.privmsg('foo', 'bar')),
+ 'PRIVMSG foo :bar\r\n')
+ self.assertEqual(str(ircmsgs.privmsg('foo,bar', 'baz')),
+ 'PRIVMSG foo,bar :baz\r\n')
+
+ def testWhois(self):
+ self.assertEqual(str(ircmsgs.whois('foo')), 'WHOIS :foo\r\n')
+ self.assertEqual(str(ircmsgs.whois('foo,bar')), 'WHOIS :foo,bar\r\n')
+ self.assertRaises(AssertionError, ircmsgs.whois, '#foo')
+ self.assertRaises(AssertionError, ircmsgs.whois, 'foo,#foo')
+
def testBan(self):
channel = '#osu'
ban = '*!*@*.edu'
Please sign in to comment.
Something went wrong with that request. Please try again.