3
0
mirror of https://github.com/jlu5/PyLink.git synced 2025-02-25 09:50:39 +01:00

unreal: actually enable the SJOIN cap, handle ban bursts properly

This commit is contained in:
James Lu 2016-12-31 22:15:42 -08:00
parent a340ab15e1
commit 278339b5e2

View File

@ -305,6 +305,7 @@ class UnrealProtocol(TS6BaseProtocol):
f('PASS :%s' % self.irc.serverdata["sendpass"]) f('PASS :%s' % self.irc.serverdata["sendpass"])
# https://github.com/unrealircd/unrealircd/blob/2f8cb55e/doc/technical/protoctl.txt # https://github.com/unrealircd/unrealircd/blob/2f8cb55e/doc/technical/protoctl.txt
# We support the following protocol features: # We support the following protocol features:
# SJOIN - supports SJOIN for user introduction
# SJ3 - extended SJOIN # SJ3 - extended SJOIN
# NOQUIT - QUIT messages aren't sent for all users in a netsplit # NOQUIT - QUIT messages aren't sent for all users in a netsplit
# NICKv2 - Extended NICK command, sending MODE and CHGHOST info with it # NICKv2 - Extended NICK command, sending MODE and CHGHOST info with it
@ -320,7 +321,7 @@ class UnrealProtocol(TS6BaseProtocol):
# not work for any UnrealIRCd 3.2 users. # not work for any UnrealIRCd 3.2 users.
# ESVID - Supports account names in services stamps instead of just the signon time. # ESVID - Supports account names in services stamps instead of just the signon time.
# AFAIK this doesn't actually affect services' behaviour? # AFAIK this doesn't actually affect services' behaviour?
f('PROTOCTL SJ3 NOQUIT NICKv2 VL UMODE2 PROTOCTL NICKIP EAUTH=%s SID=%s VHP ESVID' % (self.irc.serverdata["hostname"], self.irc.sid)) f('PROTOCTL SJOIN SJ3 NOQUIT NICKv2 VL UMODE2 PROTOCTL NICKIP EAUTH=%s SID=%s VHP ESVID' % (self.irc.serverdata["hostname"], self.irc.sid))
sdesc = self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc'] sdesc = self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc']
f('SERVER %s 1 U%s-h6e-%s :%s' % (host, self.proto_ver, self.irc.sid, sdesc)) f('SERVER %s 1 U%s-h6e-%s :%s' % (host, self.proto_ver, self.irc.sid, sdesc))
f('NETINFO 1 %s %s * 0 0 0 :%s' % (self.irc.start_ts, self.proto_ver, self.irc.serverdata.get("netname", self.irc.name))) f('NETINFO 1 %s %s * 0 0 0 :%s' % (self.irc.start_ts, self.proto_ver, self.irc.serverdata.get("netname", self.irc.name)))
@ -538,10 +539,7 @@ class UnrealProtocol(TS6BaseProtocol):
def handle_sjoin(self, numeric, command, args): def handle_sjoin(self, numeric, command, args):
"""Handles the UnrealIRCd SJOIN command.""" """Handles the UnrealIRCd SJOIN command."""
# <- :001 SJOIN 1444361345 #test :001DJ1O02 # <- :001 SJOIN 1444361345 #test :001AAAAAA @001AAAAAB +001AAAAAC
# memberlist should be a list of UIDs with their channel status prefixes, as
# in ":001AAAAAA @001AAAAAB +001AAAAAC".
# Interestingly, no modes are ever sent in this command as far as I've seen.
channel = self.irc.toLower(args[1]) channel = self.irc.toLower(args[1])
chandata = self.irc.channels[channel].deepcopy() chandata = self.irc.channels[channel].deepcopy()
userlist = args[-1].split() userlist = args[-1].split()
@ -549,35 +547,48 @@ class UnrealProtocol(TS6BaseProtocol):
namelist = [] namelist = []
log.debug('(%s) handle_sjoin: got userlist %r for %r', self.irc.name, userlist, channel) log.debug('(%s) handle_sjoin: got userlist %r for %r', self.irc.name, userlist, channel)
# Keep track of other modes that are added due to prefix modes being joined too. modestring = ''
changedmodes = set(self.irc.channels[channel].modes) # FIXME: Implement edge-case mode conflict handling as documented here:
# https://www.unrealircd.org/files/docs/technical/serverprotocol.html#S5_1
changedmodes = set()
try:
if args[2].startswith('+'):
modestring = args[2]
changedmodes = set(self.irc.parseModes(channel, modestring))
except IndexError:
pass
for userpair in userlist: for userpair in userlist:
if userpair.startswith("&\"'"): # TODO: handle ban bursts too # &, ", and ' entries are used for bursting bans:
# &, ", and ' entries are used for bursting bans: # https://www.unrealircd.org/files/docs/technical/serverprotocol.html#S5_1
# https://www.unrealircd.org/files/docs/technical/serverprotocol.html#S5_1 if userpair.startswith("&"):
break changedmodes.add(('+b', userpair[1:]))
r = re.search(r'([^\w]*)(.*)', userpair) elif userpair.startswith('"'):
user = r.group(2) changedmodes.add(('+e', userpair[1:]))
# Unreal uses slightly different prefixes in SJOIN. +q is * instead of ~, elif userpair.startswith("'"):
# and +a is ~ instead of &. changedmodes.add(('+I', userpair[1:]))
modeprefix = (r.group(1) or '').replace("~", "&").replace("*", "~") else:
finalprefix = '' r = re.search(r'([^\w]*)(.*)', userpair)
assert user, 'Failed to get the UID from %r; our regex needs updating?' % userpair user = r.group(2)
log.debug('(%s) handle_sjoin: got modeprefix %r for user %r', self.irc.name, modeprefix, user) # Unreal uses slightly different prefixes in SJOIN. +q is * instead of ~,
for m in modeprefix: # and +a is ~ instead of &.
# Iterate over the mapping of prefix chars to prefixes, and modeprefix = (r.group(1) or '').replace("~", "&").replace("*", "~")
# find the characters that match. finalprefix = ''
for char, prefix in self.irc.prefixmodes.items(): assert user, 'Failed to get the UID from %r; our regex needs updating?' % userpair
if m == prefix: log.debug('(%s) handle_sjoin: got modeprefix %r for user %r', self.irc.name, modeprefix, user)
finalprefix += char for m in modeprefix:
namelist.append(user) # Iterate over the mapping of prefix chars to prefixes, and
self.irc.users[user].channels.add(channel) # find the characters that match.
for char, prefix in self.irc.prefixmodes.items():
if m == prefix:
finalprefix += char
namelist.append(user)
self.irc.users[user].channels.add(channel)
# Only merge the remote's prefix modes if their TS is smaller or equal to ours. # Only merge the remote's prefix modes if their TS is smaller or equal to ours.
changedmodes |= {('+%s' % mode, user) for mode in finalprefix} changedmodes |= {('+%s' % mode, user) for mode in finalprefix}
self.irc.channels[channel].users.add(user) self.irc.channels[channel].users.add(user)
our_ts = self.irc.channels[channel].ts our_ts = self.irc.channels[channel].ts
their_ts = int(args[0]) their_ts = int(args[0])