mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-01 09:19:23 +01:00
relay/utils: make mode reversals work with mode changes that affect op statuses.
This commit is contained in:
parent
c82a0a771c
commit
9a139212dd
@ -116,14 +116,23 @@ def save(irc, source, args):
|
|||||||
irc.msg(source, 'Error: You are not authenticated!')
|
irc.msg(source, 'Error: You are not authenticated!')
|
||||||
return
|
return
|
||||||
|
|
||||||
def getPrefixModes(irc, remoteirc, channel, user):
|
def getPrefixModes(irc, remoteirc, channel, user, mlist=None):
|
||||||
|
"""
|
||||||
|
Fetches all prefix modes for a user in a channel that are supported by the
|
||||||
|
remote IRC network given.
|
||||||
|
|
||||||
|
Optionally, an mlist argument can be given to look at an earlier state of
|
||||||
|
the channel, e.g. for checking the op status of a mode setter before their
|
||||||
|
modes are processed and added to the channel state.
|
||||||
|
"""
|
||||||
modes = ''
|
modes = ''
|
||||||
|
mlist = mlist or irc.channels[channel].prefixmodes
|
||||||
for pmode in ('owner', 'admin', 'op', 'halfop', 'voice'):
|
for pmode in ('owner', 'admin', 'op', 'halfop', 'voice'):
|
||||||
if pmode in remoteirc.cmodes: # Mode supported by IRCd
|
if pmode in remoteirc.cmodes: # Mode supported by IRCd
|
||||||
mlist = irc.channels[channel].prefixmodes[pmode+'s']
|
userlist = mlist[pmode+'s']
|
||||||
log.debug('(%s) getPrefixModes: checking if %r is in %s list: %r',
|
log.debug('(%s) getPrefixModes: checking if %r is in %s list: %r',
|
||||||
irc.name, user, pmode, mlist)
|
irc.name, user, pmode, userlist)
|
||||||
if user in mlist:
|
if user in userlist:
|
||||||
modes += remoteirc.cmodes[pmode]
|
modes += remoteirc.cmodes[pmode]
|
||||||
return modes
|
return modes
|
||||||
|
|
||||||
@ -416,7 +425,7 @@ def handle_privmsg(irc, numeric, command, args):
|
|||||||
utils.add_hook(handle_privmsg, 'PRIVMSG')
|
utils.add_hook(handle_privmsg, 'PRIVMSG')
|
||||||
utils.add_hook(handle_privmsg, 'NOTICE')
|
utils.add_hook(handle_privmsg, 'NOTICE')
|
||||||
|
|
||||||
def checkClaim(irc, channel, sender):
|
def checkClaim(irc, channel, sender, chanobj=None):
|
||||||
"""
|
"""
|
||||||
Checks whether the sender of a kick/mode change passes CLAIM checks for
|
Checks whether the sender of a kick/mode change passes CLAIM checks for
|
||||||
a given channel. This returns True if any of the following criteria are met:
|
a given channel. This returns True if any of the following criteria are met:
|
||||||
@ -428,7 +437,13 @@ def checkClaim(irc, channel, sender):
|
|||||||
5) The originating network is the one that created the relay.
|
5) The originating network is the one that created the relay.
|
||||||
"""
|
"""
|
||||||
relay = findRelay((irc.name, channel))
|
relay = findRelay((irc.name, channel))
|
||||||
sender_modes = getPrefixModes(irc, irc, channel, sender)
|
try:
|
||||||
|
mlist = chanobj.prefixmodes
|
||||||
|
except AttributeError:
|
||||||
|
mlist = None
|
||||||
|
sender_modes = getPrefixModes(irc, irc, channel, sender, mlist=mlist)
|
||||||
|
log.debug('(%s) relay.checkClaim: sender modes (%s/%s) are %s (mlist=%s)', irc.name,
|
||||||
|
sender, channel, sender_modes, mlist)
|
||||||
return (not relay) or irc.name == relay[0] or irc.name in db[relay]['claim'] or \
|
return (not relay) or irc.name == relay[0] or irc.name in db[relay]['claim'] or \
|
||||||
any([mode in sender_modes for mode in ('y', 'q', 'a', 'o', 'h')]) \
|
any([mode in sender_modes for mode in ('y', 'q', 'a', 'o', 'h')]) \
|
||||||
or utils.isInternalClient(irc, sender) or \
|
or utils.isInternalClient(irc, sender) or \
|
||||||
@ -665,10 +680,11 @@ def handle_mode(irc, numeric, command, args):
|
|||||||
if irc.name == name or not remoteirc.connected.is_set():
|
if irc.name == name or not remoteirc.connected.is_set():
|
||||||
continue
|
continue
|
||||||
if utils.isChannel(target):
|
if utils.isChannel(target):
|
||||||
if checkClaim(irc, target, numeric):
|
oldchan = args['oldchan']
|
||||||
|
if checkClaim(irc, target, numeric, chanobj=oldchan):
|
||||||
relayModes(irc, remoteirc, numeric, target, modes)
|
relayModes(irc, remoteirc, numeric, target, modes)
|
||||||
else: # Mode change blocked by CLAIM.
|
else: # Mode change blocked by CLAIM.
|
||||||
reversed_modes = utils.reverseModes(irc, target, modes)
|
reversed_modes = utils.reverseModes(irc, target, modes, oldobj=oldchan)
|
||||||
log.debug('(%s) Reversing mode changes of %r with %r (CLAIM).',
|
log.debug('(%s) Reversing mode changes of %r with %r (CLAIM).',
|
||||||
irc.name, modes, reversed_modes)
|
irc.name, modes, reversed_modes)
|
||||||
irc.proto.modeClient(irc.pseudoclient.uid, target, reversed_modes)
|
irc.proto.modeClient(irc.pseudoclient.uid, target, reversed_modes)
|
||||||
|
27
utils.py
27
utils.py
@ -338,14 +338,19 @@ def _flip(mode):
|
|||||||
mode.insert(0, '-')
|
mode.insert(0, '-')
|
||||||
return ''.join(mode)
|
return ''.join(mode)
|
||||||
|
|
||||||
def reverseModes(irc, target, modes):
|
def reverseModes(irc, target, modes, oldobj=None):
|
||||||
"""Reverses/Inverts the mode string or mode list given.
|
"""Reverses/Inverts the mode string or mode list given.
|
||||||
|
|
||||||
"+nt-lk" => "-nt+lk"
|
Optionally, an oldobj argument can be given to look at an earlier state of
|
||||||
"nt-k" => "-nt+k"
|
a channel/user object, e.g. for checking the op status of a mode setter
|
||||||
[('+m', None), ('+t', None), ('+l', '3'), ('-o', 'person')] =>
|
before their modes are processed and added to the channel state.
|
||||||
[('-m', None), ('-t', None), ('-l', '3'), ('+o', 'person')]
|
|
||||||
[('s', None), ('+n', None)] => [('-s', None), ('-n', None)]
|
This function allows both mode strings or mode lists. Example uses:
|
||||||
|
"+mi-lk test => "-mi+lk test"
|
||||||
|
"mi-k test => "-mi+k test"
|
||||||
|
[('+m', None), ('+r', None), ('+l', '3'), ('-o', 'person')
|
||||||
|
=> {('-m', None), ('-r', None), ('-l', None), ('+o', 'person')})
|
||||||
|
{('s', None), ('+o', 'whoever') => {('-s', None), ('-o', 'whoever')})
|
||||||
"""
|
"""
|
||||||
origtype = type(modes)
|
origtype = type(modes)
|
||||||
# If the query is a string, we have to parse it first.
|
# If the query is a string, we have to parse it first.
|
||||||
@ -353,11 +358,12 @@ def reverseModes(irc, target, modes):
|
|||||||
modes = parseModes(irc, target, modes.split(" "))
|
modes = parseModes(irc, target, modes.split(" "))
|
||||||
# Get the current mode list first.
|
# Get the current mode list first.
|
||||||
if isChannel(target):
|
if isChannel(target):
|
||||||
oldmodes = irc.channels[target].modes.copy()
|
c = oldobj or irc.channels[target]
|
||||||
|
oldmodes = c.modes.copy()
|
||||||
possible_modes = irc.cmodes.copy()
|
possible_modes = irc.cmodes.copy()
|
||||||
# For channels, this also includes the list of prefix modes.
|
# For channels, this also includes the list of prefix modes.
|
||||||
possible_modes['*A'] += ''.join(irc.prefixmodes)
|
possible_modes['*A'] += ''.join(irc.prefixmodes)
|
||||||
for name, userlist in irc.channels[target].prefixmodes.items():
|
for name, userlist in c.prefixmodes.items():
|
||||||
try:
|
try:
|
||||||
oldmodes.update([(irc.cmodes[name[:-1]], u) for u in userlist])
|
oldmodes.update([(irc.cmodes[name[:-1]], u) for u in userlist])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -366,6 +372,8 @@ def reverseModes(irc, target, modes):
|
|||||||
oldmodes = irc.users[target].modes
|
oldmodes = irc.users[target].modes
|
||||||
possible_modes = irc.umodes
|
possible_modes = irc.umodes
|
||||||
newmodes = []
|
newmodes = []
|
||||||
|
log.debug('(%s) reverseModes: old/current mode list for %s is: %s', irc.name,
|
||||||
|
target, oldmodes)
|
||||||
for char, arg in modes:
|
for char, arg in modes:
|
||||||
# Mode types:
|
# Mode types:
|
||||||
# A = Mode that adds or removes a nick or address to a list. Always has a parameter.
|
# A = Mode that adds or removes a nick or address to a list. Always has a parameter.
|
||||||
@ -390,9 +398,12 @@ def reverseModes(irc, target, modes):
|
|||||||
mpair = (_flip(char), arg)
|
mpair = (_flip(char), arg)
|
||||||
if char[0] != '-' and (mchar, arg) in oldmodes:
|
if char[0] != '-' and (mchar, arg) in oldmodes:
|
||||||
# Mode is already set.
|
# Mode is already set.
|
||||||
|
log.debug("(%s) reverseModes: skipping reversing '%s %s' with %s since we're "
|
||||||
|
"setting a mode that's already set.", irc.name, char, arg, mpair)
|
||||||
continue
|
continue
|
||||||
newmodes.append(mpair)
|
newmodes.append(mpair)
|
||||||
|
|
||||||
|
log.debug('(%s) reverseModes: new modes: %s', irc.name, newmodes)
|
||||||
if origtype == str:
|
if origtype == str:
|
||||||
# If the original query is a string, send it back as a string.
|
# If the original query is a string, send it back as a string.
|
||||||
return joinModes(newmodes)
|
return joinModes(newmodes)
|
||||||
|
Loading…
Reference in New Issue
Block a user