mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-23 19:19:31 +01:00
relay: support relaying kills (#520)
Instead of always bouncing, kills to a relay client are now handled as follows: 1) If the target and source networks are both in any killshare pool, relay the kill entirely 2) Otherwise, iterate over all channels the kill target is in: 3) If the killer has claim access in a channel, forward the KILL as a kick 4) Otherwise, bounce the kill (so far, silently) TODO: kill messages are currently very cluttered, we should make our parser deliver more concise strings... * GL|unreal has quit (Killed (chary.relay (KILL from GL/chary: Killed (GL (test)))))
This commit is contained in:
parent
9466813ba1
commit
73d0e153cf
@ -659,6 +659,15 @@ relay:
|
||||
# - ["net1", "net2", "net3"]
|
||||
# - ["net1", "meganet"]
|
||||
|
||||
# This option defines lists of networks that kills should be relayed between.
|
||||
# If a network is in a pool (case-SENSITIVE), they will be able to kill users
|
||||
# on other networks in the pool, and will also receive kills from other networks
|
||||
# in the pool.
|
||||
# You should generally have a consensus among your linked networks as to which
|
||||
# network should be in which pool.
|
||||
#kill_share_pools:
|
||||
# - ["net1", "net2", "net3"]
|
||||
|
||||
# Determines whether NickServ login info should be shown in the /whois output for
|
||||
# relay users.
|
||||
# Valid options include "all" (show this to everyone), "opers" (show only to
|
||||
|
@ -326,7 +326,7 @@ def _has_common_pool(sourcenet, targetnet, namespace):
|
||||
if 'relay' not in conf.conf:
|
||||
return False
|
||||
|
||||
for pool in conf.conf['relay'].get(namespace, []):
|
||||
for pool in (conf.conf['relay'].get(namespace) or []):
|
||||
if sourcenet in pool and targetnet in pool:
|
||||
log.debug('relay._has_common_pool: found networks %r and %r in %s pool %r', sourcenet, targetnet,
|
||||
namespace, pool)
|
||||
@ -1905,30 +1905,54 @@ def handle_kill(irc, numeric, command, args):
|
||||
|
||||
# Target user was remote:
|
||||
if realuser and realuser[0] != irc.name:
|
||||
# We don't allow killing over the relay, so we must respawn the affected
|
||||
# client and rejoin it to its channels.
|
||||
del relayusers[realuser][irc.name]
|
||||
remoteirc = world.networkobjects[realuser[0]]
|
||||
for remotechan in remoteirc.users[realuser[1]].channels:
|
||||
localchan = get_remote_channel(remoteirc, irc, remotechan)
|
||||
if localchan:
|
||||
modes = get_prefix_modes(remoteirc, irc, remotechan, realuser[1])
|
||||
log.debug('(%s) relay.handle_kill: userpair: %s, %s', irc.name, modes, realuser)
|
||||
client = get_remote_user(remoteirc, irc, realuser[1], times_tagged=1)
|
||||
irc.sjoin(get_relay_server_sid(irc, remoteirc), localchan, [(modes, client)])
|
||||
fwd_reason = 'KILL from %s/%s: %s' % (irc.get_friendly_name(numeric), irc.name, args['text'])
|
||||
|
||||
if userdata and numeric in irc.users:
|
||||
log.info('(%s) relay.handle_kill: Blocked KILL (reason %r) from %s to relay client %s/%s.',
|
||||
irc.name, args['text'], irc.users[numeric].nick,
|
||||
remoteirc.users[realuser[1]].nick, realuser[0])
|
||||
irc.msg(numeric, "Your kill to %s has been blocked "
|
||||
"because PyLink does not allow killing"
|
||||
" users over the relay at this time." % \
|
||||
userdata.nick, notice=True)
|
||||
origirc = world.networkobjects[realuser[0]]
|
||||
|
||||
# If we're allowed to forward kills, then do so.
|
||||
if _has_common_pool(irc.name, realuser[0], 'kill_share_pools'):
|
||||
def _relay_kill_loop(irc, remoteirc):
|
||||
if remoteirc == origirc:
|
||||
# Don't bother with get_orig_user when we relay onto the target's home net
|
||||
rtarget = realuser[1]
|
||||
else:
|
||||
log.info('(%s) relay.handle_kill: Blocked KILL (reason %r) from server %s to relay client %s/%s.',
|
||||
irc.name, args['text'], irc.servers[numeric].name,
|
||||
remoteirc.users[realuser[1]].nick, realuser[0])
|
||||
rtarget = get_remote_user(origirc, remoteirc, realuser[1])
|
||||
|
||||
if rtarget:
|
||||
# Forward the kill from the relay server when available
|
||||
rsender = get_relay_server_sid(remoteirc, irc, spawn_if_missing=False) or \
|
||||
remoteirc.sid
|
||||
remoteirc.kill(rsender, rtarget, fwd_reason)
|
||||
|
||||
iterate_all(irc, _relay_kill_loop)
|
||||
|
||||
del relayusers[realuser]
|
||||
else:
|
||||
# Otherwise, forward kills as kicks where applicable.
|
||||
for remotechan in origirc.users[realuser[1]].channels.copy():
|
||||
localchan = get_remote_channel(origirc, irc, remotechan)
|
||||
|
||||
if localchan:
|
||||
# Forward kills as kicks in all channels that the sender has CLAIM access to.
|
||||
if check_claim(irc, localchan, numeric):
|
||||
rsid = get_relay_server_sid(origirc, irc)
|
||||
log.debug('(%s) relay.handle_kill: forwarding kill to %s/%s@%s as '
|
||||
'kick on %s', irc.name, realuser[1],
|
||||
origirc.get_friendly_name(realuser[1]), realuser[0], remotechan)
|
||||
|
||||
origirc.kick(rsid, remotechan, realuser[1], fwd_reason)
|
||||
origirc.call_hooks([rsid, 'RELAY_KILLFORWARD_KICK',
|
||||
{'target': realuser[1], 'channel': remotechan, 'text': fwd_reason,
|
||||
'parse_as': 'KICK'}])
|
||||
|
||||
# If we have no access in a channel, rejoin the target.
|
||||
else:
|
||||
modes = get_prefix_modes(origirc, irc, remotechan, realuser[1])
|
||||
log.debug('(%s) relay.handle_kill: rejoining target userpair: (%r, %r)', irc.name, modes, realuser)
|
||||
# Set times_tagged=1 to forcetag the target when they return.
|
||||
client = get_remote_user(origirc, irc, realuser[1], times_tagged=1)
|
||||
irc.sjoin(irc.sid, localchan, [(modes, client)])
|
||||
|
||||
# Target user was local.
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user