mirror of
https://github.com/progval/Limnoria.git
synced 2025-04-26 04:51:06 -05:00
Replace makeExtBanmask with makeExtBanmasks
Now that we can return both account extbans and regular masks, it makes sense to ban both. Otherwise, adding 'account' to supybot.protocols.irc.banmask means we banned only the account instead of the hostmask, which arguably makes the ban weaker (/NS LOGOUT to evade)
This commit is contained in:
parent
fc49d17faa
commit
f73fe5095e
@ -163,9 +163,9 @@ class AutoMode(callbacks.Plugin):
|
|||||||
# We're not in the channel anymore.
|
# We're not in the channel anymore.
|
||||||
pass
|
pass
|
||||||
schedule.addEvent(unban, time.time()+period)
|
schedule.addEvent(unban, time.time()+period)
|
||||||
banmask = conf.supybot.protocols.irc.banmask.makeExtBanmask(
|
banmasks = conf.supybot.protocols.irc.banmask.makeExtBanmasks(
|
||||||
msg.prefix, channel=channel, network=irc.network)
|
msg.prefix, channel=channel, network=irc.network)
|
||||||
irc.queueMsg(ircmsgs.ban(channel, banmask))
|
irc.queueMsg(ircmsgs.bans(channel, banmasks))
|
||||||
irc.queueMsg(ircmsgs.kick(channel, msg.nick))
|
irc.queueMsg(ircmsgs.kick(channel, msg.nick))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -368,7 +368,7 @@ class Channel(callbacks.Plugin):
|
|||||||
try:
|
try:
|
||||||
bannedHostmask = irc.state.nickToHostmask(target)
|
bannedHostmask = irc.state.nickToHostmask(target)
|
||||||
banmaskstyle = conf.supybot.protocols.irc.banmask
|
banmaskstyle = conf.supybot.protocols.irc.banmask
|
||||||
banmask = banmaskstyle.makeExtBanmask(
|
banmasks = banmaskstyle.makeExtBanmasks(
|
||||||
bannedHostmask, [o[0] for o in optlist],
|
bannedHostmask, [o[0] for o in optlist],
|
||||||
channel=channel, network=irc.network)
|
channel=channel, network=irc.network)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -376,12 +376,14 @@ class Channel(callbacks.Plugin):
|
|||||||
target.startswith('$'):
|
target.startswith('$'):
|
||||||
# Select the last part, or the whole target:
|
# Select the last part, or the whole target:
|
||||||
bannedNick = target.split(':')[-1]
|
bannedNick = target.split(':')[-1]
|
||||||
banmask = bannedHostmask = target
|
bannedHostmask = target
|
||||||
|
banmasks = [bannedHostmask]
|
||||||
else:
|
else:
|
||||||
irc.error(format(_('I haven\'t seen %s.'), bannedNick), Raise=True)
|
irc.error(format(_('I haven\'t seen %s.'), bannedNick), Raise=True)
|
||||||
else:
|
else:
|
||||||
bannedNick = ircutils.nickFromHostmask(target)
|
bannedNick = ircutils.nickFromHostmask(target)
|
||||||
banmask = bannedHostmask = target
|
bannedHostmask = target
|
||||||
|
banmasks = [bannedHostmask]
|
||||||
if not irc.isNick(bannedNick):
|
if not irc.isNick(bannedNick):
|
||||||
self.log.warning('%q tried to kban a non nick: %q',
|
self.log.warning('%q tried to kban a non nick: %q',
|
||||||
msg.prefix, bannedNick)
|
msg.prefix, bannedNick)
|
||||||
@ -398,6 +400,8 @@ class Channel(callbacks.Plugin):
|
|||||||
reason = msg.nick
|
reason = msg.nick
|
||||||
capability = ircdb.makeChannelCapability(channel, 'op')
|
capability = ircdb.makeChannelCapability(channel, 'op')
|
||||||
# Check (again) that they're not trying to make us kickban ourself.
|
# Check (again) that they're not trying to make us kickban ourself.
|
||||||
|
for banmask in banmasks:
|
||||||
|
# TODO: check account ban too
|
||||||
if ircutils.hostmaskPatternEqual(banmask, irc.prefix):
|
if ircutils.hostmaskPatternEqual(banmask, irc.prefix):
|
||||||
if ircutils.hostmaskPatternEqual(bannedHostmask, irc.prefix):
|
if ircutils.hostmaskPatternEqual(bannedHostmask, irc.prefix):
|
||||||
self.log.warning('%q tried to make me kban myself.',msg.prefix)
|
self.log.warning('%q tried to make me kban myself.',msg.prefix)
|
||||||
@ -406,21 +410,28 @@ class Channel(callbacks.Plugin):
|
|||||||
else:
|
else:
|
||||||
self.log.warning('Using exact hostmask since banmask would '
|
self.log.warning('Using exact hostmask since banmask would '
|
||||||
'ban myself.')
|
'ban myself.')
|
||||||
banmask = bannedHostmask
|
banmasks = [bannedHostmask]
|
||||||
# Now, let's actually get to it. Check to make sure they have
|
# Now, let's actually get to it. Check to make sure they have
|
||||||
# #channel,op and the bannee doesn't have #channel,op; or that the
|
# #channel,op and the bannee doesn't have #channel,op; or that the
|
||||||
# bannee and the banner are both the same person.
|
# bannee and the banner are both the same person.
|
||||||
def doBan():
|
def doBan():
|
||||||
if irc.state.channels[channel].isOp(bannedNick):
|
if irc.state.channels[channel].isOp(bannedNick):
|
||||||
irc.queueMsg(ircmsgs.deop(channel, bannedNick))
|
irc.queueMsg(ircmsgs.deop(channel, bannedNick))
|
||||||
irc.queueMsg(ircmsgs.ban(channel, banmask))
|
irc.queueMsg(ircmsgs.bans(channel, banmasks))
|
||||||
if kick:
|
if kick:
|
||||||
irc.queueMsg(ircmsgs.kick(channel, bannedNick, reason))
|
irc.queueMsg(ircmsgs.kick(channel, bannedNick, reason))
|
||||||
if expiry > 0:
|
if expiry > 0:
|
||||||
def f():
|
def f():
|
||||||
if channel in irc.state.channels and \
|
if channel not in irc.state.channels:
|
||||||
banmask in irc.state.channels[channel].bans:
|
return
|
||||||
irc.queueMsg(ircmsgs.unban(channel, banmask))
|
remaining_banmasks = [
|
||||||
|
banmask
|
||||||
|
for banmask in banmasks
|
||||||
|
if banmask in irc.state.channels[channel].bans
|
||||||
|
]
|
||||||
|
if remaining_banmasks:
|
||||||
|
irc.queueMsg(ircmsgs.unbans(
|
||||||
|
channel, remaining_banmasks))
|
||||||
schedule.addEvent(f, expiry)
|
schedule.addEvent(f, expiry)
|
||||||
if bannedNick == msg.nick:
|
if bannedNick == msg.nick:
|
||||||
doBan()
|
doBan()
|
||||||
@ -591,7 +602,7 @@ class Channel(callbacks.Plugin):
|
|||||||
hostmask = wrap(hostmask, ['op', ('haveHalfop+', _('ban someone')), 'text'])
|
hostmask = wrap(hostmask, ['op', ('haveHalfop+', _('ban someone')), 'text'])
|
||||||
|
|
||||||
@internationalizeDocstring
|
@internationalizeDocstring
|
||||||
def add(self, irc, msg, args, channel, banmask, expires):
|
def add(self, irc, msg, args, channel, banmasks, expires):
|
||||||
"""[<channel>] <nick|hostmask> [<expires>]
|
"""[<channel>] <nick|hostmask> [<expires>]
|
||||||
|
|
||||||
If you have the #channel,op capability, this will effect a
|
If you have the #channel,op capability, this will effect a
|
||||||
@ -605,11 +616,14 @@ class Channel(callbacks.Plugin):
|
|||||||
channel itself.
|
channel itself.
|
||||||
"""
|
"""
|
||||||
c = ircdb.channels.getChannel(channel)
|
c = ircdb.channels.getChannel(channel)
|
||||||
|
if isinstance(banmasks, str):
|
||||||
|
banmasks = [banmasks]
|
||||||
|
for banmask in banmasks:
|
||||||
c.addBan(banmask, expires)
|
c.addBan(banmask, expires)
|
||||||
ircdb.channels.setChannel(channel, c)
|
ircdb.channels.setChannel(channel, c)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
add = wrap(add, ['op',
|
add = wrap(add, ['op',
|
||||||
first('hostmask', 'extbanmask'),
|
first('hostmask', 'extbanmasks'),
|
||||||
additional('expiry', 0)])
|
additional('expiry', 0)])
|
||||||
|
|
||||||
@internationalizeDocstring
|
@internationalizeDocstring
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
# POSSIBILITY OF SUCH DAMAGE.
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
###
|
###
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
|
||||||
from supybot.test import *
|
from supybot.test import *
|
||||||
|
|
||||||
import supybot.conf as conf
|
import supybot.conf as conf
|
||||||
@ -161,9 +163,13 @@ class ChannelTestCase(ChannelPluginTestCase):
|
|||||||
self.assertTrue(m.command == 'MODE' and
|
self.assertTrue(m.command == 'MODE' and
|
||||||
m.args == (self.channel, '+v', 'bar'))
|
m.args == (self.channel, '+v', 'bar'))
|
||||||
|
|
||||||
def assertKban(self, query, hostmask, **kwargs):
|
def assertKban(self, query, *hostmasks, **kwargs):
|
||||||
m = self.getMsg(query, **kwargs)
|
m = self.getMsg(query, **kwargs)
|
||||||
self.assertEqual(m, ircmsgs.ban(self.channel, hostmask))
|
self.assertIn(m, [
|
||||||
|
ircmsgs.bans(self.channel, permutation)
|
||||||
|
for permutation in itertools.permutations(hostmasks)
|
||||||
|
])
|
||||||
|
|
||||||
m = self.getMsg(' ')
|
m = self.getMsg(' ')
|
||||||
self.assertEqual(m.command, 'KICK')
|
self.assertEqual(m.command, 'KICK')
|
||||||
def assertBan(self, query, hostmask, **kwargs):
|
def assertBan(self, query, hostmask, **kwargs):
|
||||||
@ -278,25 +284,29 @@ class ChannelTestCase(ChannelPluginTestCase):
|
|||||||
for style in (['exact'], ['account', 'exact']):
|
for style in (['exact'], ['account', 'exact']):
|
||||||
with conf.supybot.protocols.irc.banmask.context(style):
|
with conf.supybot.protocols.irc.banmask.context(style):
|
||||||
self.assertKban('kban --account --exact foobar',
|
self.assertKban('kban --account --exact foobar',
|
||||||
'~a:account1')
|
'~a:account1', 'foobar!user@host.domain.tld')
|
||||||
join()
|
join()
|
||||||
self.assertKban('kban --account foobar',
|
self.assertKban('kban --account foobar',
|
||||||
'~a:account1')
|
'~a:account1')
|
||||||
join()
|
join()
|
||||||
self.assertKban('kban --account --host foobar',
|
self.assertKban('kban --account --host foobar',
|
||||||
'~a:account1')
|
'~a:account1', '*!*@host.domain.tld')
|
||||||
join()
|
join()
|
||||||
|
|
||||||
with conf.supybot.protocols.irc.banmask.context(['account', 'exact']):
|
with conf.supybot.protocols.irc.banmask.context(['account', 'exact']):
|
||||||
self.assertKban('kban foobar',
|
self.assertKban('kban foobar',
|
||||||
'~a:account1')
|
'~a:account1', 'foobar!user@host.domain.tld')
|
||||||
|
join()
|
||||||
|
|
||||||
|
with conf.supybot.protocols.irc.banmask.context(['account', 'host']):
|
||||||
|
self.assertKban('kban foobar',
|
||||||
|
'~a:account1', '*!*@host.domain.tld')
|
||||||
join()
|
join()
|
||||||
|
|
||||||
def testBan(self):
|
def testBan(self):
|
||||||
with conf.supybot.protocols.irc.banmask.context(['exact']):
|
with conf.supybot.protocols.irc.banmask.context(['exact']):
|
||||||
self.assertNotError('ban add foo!bar@baz')
|
self.assertNotError('ban add foo!bar@baz')
|
||||||
self.assertNotError('ban remove foo!bar@baz')
|
self.assertNotError('ban remove foo!bar@baz')
|
||||||
orig = conf.supybot.protocols.irc.strictRfc()
|
|
||||||
with conf.supybot.protocols.irc.strictRfc.context(True):
|
with conf.supybot.protocols.irc.strictRfc.context(True):
|
||||||
# something wonky is going on here. irc.error (src/Channel.py|449)
|
# something wonky is going on here. irc.error (src/Channel.py|449)
|
||||||
# is being called but the assert is failing
|
# is being called but the assert is failing
|
||||||
@ -322,7 +332,6 @@ class ChannelTestCase(ChannelPluginTestCase):
|
|||||||
'"foobar!*@baz" (never expires)')
|
'"foobar!*@baz" (never expires)')
|
||||||
|
|
||||||
def testIgnore(self):
|
def testIgnore(self):
|
||||||
orig = conf.supybot.protocols.irc.banmask()
|
|
||||||
def ignore(given, expect=None):
|
def ignore(given, expect=None):
|
||||||
if expect is None:
|
if expect is None:
|
||||||
expect = given
|
expect = given
|
||||||
@ -330,6 +339,7 @@ class ChannelTestCase(ChannelPluginTestCase):
|
|||||||
self.assertResponse('channel ignore list', "'%s'" % expect)
|
self.assertResponse('channel ignore list', "'%s'" % expect)
|
||||||
self.assertNotError('channel ignore remove %s' % expect)
|
self.assertNotError('channel ignore remove %s' % expect)
|
||||||
self.assertRegexp('channel ignore list', 'not currently')
|
self.assertRegexp('channel ignore list', 'not currently')
|
||||||
|
with conf.supybot.protocols.irc.banmask.context(['host']):
|
||||||
ignore('foo!bar@baz', '*!*@baz')
|
ignore('foo!bar@baz', '*!*@baz')
|
||||||
ignore('foo!*@*')
|
ignore('foo!*@*')
|
||||||
with conf.supybot.protocols.irc.banmask.context(['exact']):
|
with conf.supybot.protocols.irc.banmask.context(['exact']):
|
||||||
|
@ -437,11 +437,11 @@ def getBanmask(irc, msg, args, state):
|
|||||||
state.args[-1] = banmaskstyle.makeBanmask(state.args[-1],
|
state.args[-1] = banmaskstyle.makeBanmask(state.args[-1],
|
||||||
channel=state.channel, network=irc.network)
|
channel=state.channel, network=irc.network)
|
||||||
|
|
||||||
def getExtBanmask(irc, msg, args, state):
|
def getExtBanmasks(irc, msg, args, state):
|
||||||
getHostmask(irc, msg, args, state)
|
getHostmask(irc, msg, args, state)
|
||||||
getChannel(irc, msg, args, state)
|
getChannel(irc, msg, args, state)
|
||||||
banmaskstyle = conf.supybot.protocols.irc.extbanmask
|
banmaskstyle = conf.supybot.protocols.irc.extbanmask
|
||||||
state.args[-1] = banmaskstyle.makeExtBanmask(state.args[-1],
|
state.args[-1] = banmaskstyle.makeExtBanmasks(state.args[-1],
|
||||||
channel=state.channel, network=irc.network)
|
channel=state.channel, network=irc.network)
|
||||||
|
|
||||||
def getUser(irc, msg, args, state):
|
def getUser(irc, msg, args, state):
|
||||||
@ -813,7 +813,7 @@ wrappers = ircutils.IrcDict({
|
|||||||
'commandName': getCommandName,
|
'commandName': getCommandName,
|
||||||
'email': getEmail,
|
'email': getEmail,
|
||||||
'expiry': getExpiry,
|
'expiry': getExpiry,
|
||||||
'extbanmask': getExtBanmask,
|
'extbanmasks': getExtBanmasks,
|
||||||
'filename': getSomething, # XXX Check for validity.
|
'filename': getSomething, # XXX Check for validity.
|
||||||
'float': getFloat,
|
'float': getFloat,
|
||||||
'glob': getGlob,
|
'glob': getGlob,
|
||||||
|
37
src/conf.py
37
src/conf.py
@ -1215,7 +1215,7 @@ class Banmask(registry.SpaceSeparatedSetOfStrings):
|
|||||||
isn't specified via options, the value of
|
isn't specified via options, the value of
|
||||||
conf.supybot.protocols.irc.banmask is used.
|
conf.supybot.protocols.irc.banmask is used.
|
||||||
|
|
||||||
Unlike :meth:`makeExtBanmask`, this is guaranteed to return an
|
Unlike :meth:`makeExtBanmasks`, this is guaranteed to return an
|
||||||
RFC1459-like mask, suitable for ircdb's ignore lists.
|
RFC1459-like mask, suitable for ircdb's ignore lists.
|
||||||
|
|
||||||
options - A list specifying which parts of the hostmask should
|
options - A list specifying which parts of the hostmask should
|
||||||
@ -1228,10 +1228,15 @@ class Banmask(registry.SpaceSeparatedSetOfStrings):
|
|||||||
options = supybot.protocols.irc.banmask.getSpecific(
|
options = supybot.protocols.irc.banmask.getSpecific(
|
||||||
network, channel)()
|
network, channel)()
|
||||||
options = [option for option in options if option != 'account']
|
options = [option for option in options if option != 'account']
|
||||||
return self.makeExtBanmask(hostmask, options, channel, network=network)
|
print(hostmask, options)
|
||||||
|
masks = self.makeExtBanmasks(
|
||||||
|
hostmask, options, channel, network=network)
|
||||||
|
assert len(masks) == 1, 'Unexpected number of banmasks: %r' % masks
|
||||||
|
print(masks)
|
||||||
|
return masks[0]
|
||||||
|
|
||||||
def makeExtBanmask(self, hostmask, options=None, channel=None, *, network):
|
def makeExtBanmasks(self, hostmask, options=None, channel=None, *, network):
|
||||||
"""Create a banmask from the given hostmask. If a style of banmask
|
"""Create banmasks from the given hostmask. If a style of banmask
|
||||||
isn't specified via options, the value of
|
isn't specified via options, the value of
|
||||||
conf.supybot.protocols.irc.banmask is used.
|
conf.supybot.protocols.irc.banmask is used.
|
||||||
|
|
||||||
@ -1256,15 +1261,22 @@ class Banmask(registry.SpaceSeparatedSetOfStrings):
|
|||||||
if not options:
|
if not options:
|
||||||
options = supybot.protocols.irc.banmask.getSpecific(
|
options = supybot.protocols.irc.banmask.getSpecific(
|
||||||
network, channel)()
|
network, channel)()
|
||||||
|
|
||||||
|
add_star_mask = False
|
||||||
|
masks = []
|
||||||
|
|
||||||
for option in options:
|
for option in options:
|
||||||
if option == 'nick':
|
if option == 'nick':
|
||||||
bnick = nick
|
bnick = nick
|
||||||
|
add_star_mask = True
|
||||||
elif option == 'user':
|
elif option == 'user':
|
||||||
buser = user
|
buser = user
|
||||||
|
add_star_mask = True
|
||||||
elif option == 'host':
|
elif option == 'host':
|
||||||
bhost = host
|
bhost = host
|
||||||
|
add_star_mask = True
|
||||||
elif option == 'exact':
|
elif option == 'exact':
|
||||||
return hostmask
|
masks.append(hostmask)
|
||||||
elif option == 'account':
|
elif option == 'account':
|
||||||
import supybot.world as world
|
import supybot.world as world
|
||||||
irc = world.getIrc(network)
|
irc = world.getIrc(network)
|
||||||
@ -1272,11 +1284,18 @@ class Banmask(registry.SpaceSeparatedSetOfStrings):
|
|||||||
continue
|
continue
|
||||||
extban = ircutils.accountExtban(nick, irc)
|
extban = ircutils.accountExtban(nick, irc)
|
||||||
if extban is not None:
|
if extban is not None:
|
||||||
return extban
|
masks.append(extban)
|
||||||
|
|
||||||
|
if add_star_mask and (bnick, buser, bhost) != ('*', '*', '*'):
|
||||||
|
masks.append(ircutils.joinHostmask(bnick, buser, bhost))
|
||||||
|
|
||||||
if (bnick, buser, bhost) == ('*', '*', '*') and \
|
if (bnick, buser, bhost) == ('*', '*', '*') and \
|
||||||
ircutils.isUserHostmask(hostmask):
|
ircutils.isUserHostmask(hostmask) and \
|
||||||
return hostmask
|
masks == []:
|
||||||
return ircutils.joinHostmask(bnick, buser, bhost)
|
masks.append(hostmask)
|
||||||
|
|
||||||
|
return masks
|
||||||
|
|
||||||
|
|
||||||
registerChannelValue(supybot.protocols.irc, 'banmask',
|
registerChannelValue(supybot.protocols.irc, 'banmask',
|
||||||
Banmask(['host'], _("""Determines what will be used as the
|
Banmask(['host'], _("""Determines what will be used as the
|
||||||
|
Loading…
x
Reference in New Issue
Block a user