3
0
mirror of https://github.com/jlu5/PyLink.git synced 2025-01-23 18:54:05 +01:00

relay: add basic support for STATUSMSG (#570)

So far, this code only knows about changing prefixes while keeping mode characters as-is.
A complete but longer solution would be to actually go through irc.cmodes, but I don't
think doing so is necessary given how little STATUSMSG is actually used in production.
This commit is contained in:
James Lu 2018-02-18 21:49:58 -08:00
parent 1405b01597
commit 81bd1e8474

View File

@ -1329,6 +1329,16 @@ def handle_part(irc, numeric, command, args):
utils.add_hook(handle_part, 'PART') utils.add_hook(handle_part, 'PART')
def _get_highest_prefix(prefixes):
if not prefixes:
return ''
for prefix in 'qyaohv':
if prefix in prefixes:
return prefix
else:
log.warning('relay._get_highest_prefix: unknown prefixes string %r', prefixes)
return ''
def handle_messages(irc, numeric, command, args): def handle_messages(irc, numeric, command, args):
command = command.upper() command = command.upper()
notice = 'NOTICE' in command or command.startswith('WALL') notice = 'NOTICE' in command or command.startswith('WALL')
@ -1347,17 +1357,19 @@ def handle_messages(irc, numeric, command, args):
relay = get_relay(irc, target) relay = get_relay(irc, target)
remoteusers = relayusers[(irc.name, numeric)] remoteusers = relayusers[(irc.name, numeric)]
# HACK: Don't break on sending to @#channel or similar. TODO: This should really avail_prefixes = {v: k for k, v in irc.prefixmodes.items()}
# be handled more neatly in core. prefixes = []
try: # Split up @#channel prefixes and the like into their prefixes and target components
prefix, target = target.split('#', 1) while target and target[0] in avail_prefixes:
except ValueError: prefixes.append(avail_prefixes[target[0]])
prefix = '' target = target[1:]
else:
target = '#' + target log.debug('(%s) relay.handle_messages: splitting target %r into prefixes=%r, target=%r',
irc.name, args['target'], prefixes, target)
if irc.is_channel(target): if irc.is_channel(target):
def _handle_messages_loop(irc, remoteirc, numeric, command, args, notice, target, text): def _handle_messages_loop(irc, remoteirc, numeric, command, args, notice,
target, text, msgprefixes):
real_target = get_remote_channel(irc, remoteirc, target) real_target = get_remote_channel(irc, remoteirc, target)
# Don't relay anything back to the source net, or to disconnected networks # Don't relay anything back to the source net, or to disconnected networks
@ -1365,6 +1377,31 @@ def handle_messages(irc, numeric, command, args):
if (not real_target) or (not irc.connected.is_set()): if (not real_target) or (not irc.connected.is_set()):
return return
orig_msgprefixes = msgprefixes
# Filter @#channel prefixes by what's available on the target network
msgprefixes = list(filter(lambda p: p in remoteirc.prefixmodes, msgprefixes))
log.debug("(%s) relay: filtering message prefixes for %s%s from %s to %s",
irc.name, remoteirc.name, real_target, orig_msgprefixes,
msgprefixes)
# If we originally had message prefixes but ended with none,
# assume that we don't have a place to forward the message and drop it.
# One exception though is that %#channel implies @#channel.
if orig_msgprefixes and not msgprefixes:
if 'h' in orig_msgprefixes:
msgprefixes.append('o')
else:
log.debug("(%s) relay: dropping message for %s%s, orig_prefixes=%r since "
"prefixes were empty after filtering.", irc.name,
remoteirc.name, real_target, orig_msgprefixes)
return
# This bit of filtering exists because some IRCds let you do /msg ~@#channel
# and such, despite its redundancy. (This is equivalent to ~#channel AFAIK)
highest_msgprefix = _get_highest_prefix(msgprefixes)
highest_msgprefix = remoteirc.prefixmodes.get(highest_msgprefix, '')
real_target = highest_msgprefix + real_target
user = get_remote_user(irc, remoteirc, numeric, spawn_if_missing=False) user = get_remote_user(irc, remoteirc, numeric, spawn_if_missing=False)
if not user: if not user:
@ -1403,7 +1440,6 @@ def handle_messages(irc, numeric, command, args):
else: else:
real_text = text real_text = text
real_target = prefix + real_target
log.debug('(%s) relay.handle_messages: sending message to %s from %s on behalf of %s', log.debug('(%s) relay.handle_messages: sending message to %s from %s on behalf of %s',
irc.name, real_target, user, numeric) irc.name, real_target, user, numeric)
@ -1425,7 +1461,8 @@ def handle_messages(irc, numeric, command, args):
"trying to send a message through it!", irc.name, "trying to send a message through it!", irc.name,
remoteirc.name, user) remoteirc.name, user)
return return
iterate_all(irc, _handle_messages_loop, extra_args=(numeric, command, args, notice, target, text)) iterate_all(irc, _handle_messages_loop,
extra_args=(numeric, command, args, notice, target, text, prefixes))
else: else:
# Get the real user that the PM was meant for # Get the real user that the PM was meant for