mirror of
https://github.com/jlu5/PyLink.git
synced 2025-01-11 12:42:34 +01:00
core: make inbound SJOINs also respect the updateTS() rules
This commit is contained in:
parent
90ee20ee8b
commit
f2b139c828
46
classes.py
46
classes.py
@ -497,10 +497,6 @@ class Irc():
|
||||
else:
|
||||
log.debug('(%s) Using self.cmodes for this query: %s', self.name, self.cmodes)
|
||||
|
||||
if target not in self.channels:
|
||||
log.warning('(%s) Possible desync! Mode target %s is not in the channels index.', self.name, target)
|
||||
return []
|
||||
|
||||
supported_modes = self.cmodes
|
||||
oldmodes = self.channels[target].modes
|
||||
res = []
|
||||
@ -1067,17 +1063,12 @@ class Protocol():
|
||||
log.debug('Removing client %s from self.irc.servers[%s].users', numeric, sid)
|
||||
self.irc.servers[sid].users.discard(numeric)
|
||||
|
||||
def updateTS(self, channel, their_ts, modes=[]):
|
||||
def updateTS(self, channel, their_ts, modes=[], outbound=True):
|
||||
"""
|
||||
Merges modes of a channel given the remote TS and a list of modes.
|
||||
|
||||
This returns True when our modes apply (our TS <= theirs)
|
||||
"""
|
||||
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
|
||||
if their_ts < our_ts:
|
||||
# Their TS is older than ours. Clear all modes.
|
||||
def _clear():
|
||||
log.debug('(%s) Setting channel TS of %s to %s from %s',
|
||||
self.irc.name, channel, their_ts, our_ts)
|
||||
self.irc.channels[channel].ts = their_ts
|
||||
@ -1086,17 +1077,36 @@ class Protocol():
|
||||
for p in self.irc.channels[channel].prefixmodes.values():
|
||||
p.clear()
|
||||
|
||||
return False
|
||||
def _apply():
|
||||
self.irc.applyModes(channel, modes)
|
||||
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
|
||||
if their_ts < our_ts:
|
||||
# Their TS is older than ours. If we're receiving a mode change, we should
|
||||
# clear our stored modes for the channel and apply theirs. Otherwise, if we're
|
||||
# the one setting modes, just drop them.
|
||||
log.debug("(%s/%s) remote TS of %s is lower than ours %s; outbound mode: %s; setting modes %s",
|
||||
self.irc.name, channel, their_ts, our_ts, outbound, modes)
|
||||
if not outbound:
|
||||
_clear()
|
||||
_apply()
|
||||
|
||||
elif their_ts == our_ts:
|
||||
log.debug("(%s/%s) remote TS of %s is equal to ours %s; outbound mode: %s; setting modes %s",
|
||||
self.irc.name, channel, their_ts, our_ts, outbound, modes)
|
||||
# Their TS is equal to ours. Merge modes.
|
||||
self.irc.applyModes(channel, modes)
|
||||
return True
|
||||
_apply()
|
||||
|
||||
elif their_ts > our_ts:
|
||||
# Their TS is younger than ours. Replace their modes with ours.
|
||||
self.irc.channels[channel].modes.clear()
|
||||
self.irc.applyModes(channel, modes)
|
||||
return True
|
||||
log.debug("(%s/%s) remote TS of %s is higher than ours %s; outbound mode: %s; setting modes %s",
|
||||
self.irc.name, channel, their_ts, our_ts, outbound, modes)
|
||||
# Their TS is younger than ours. If we're setting modes, clear the state
|
||||
# and replace the modes for the channel with ours. Otherwise, just ignore the
|
||||
# remote's changes.
|
||||
if outbound:
|
||||
_clear()
|
||||
_apply()
|
||||
|
||||
def _getSid(self, sname):
|
||||
"""Returns the SID of a server with the given name, if present."""
|
||||
|
@ -498,14 +498,14 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
# InspIRCd sends each channel's users in the form of 'modeprefix(es),UID'
|
||||
userlist = args[-1].split()
|
||||
|
||||
their_ts = int(args[1])
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
self.updateTS(channel, their_ts)
|
||||
|
||||
modestring = args[2:-1] or args[2]
|
||||
parsedmodes = self.irc.parseModes(channel, modestring)
|
||||
self.irc.applyModes(channel, parsedmodes)
|
||||
namelist = []
|
||||
|
||||
# Keep track of other modes that are added due to prefix modes being joined too.
|
||||
changedmodes = set(parsedmodes)
|
||||
|
||||
for user in userlist:
|
||||
modeprefix, user = user.split(',', 1)
|
||||
|
||||
@ -517,9 +517,17 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
|
||||
namelist.append(user)
|
||||
self.irc.users[user].channels.add(channel)
|
||||
if their_ts <= our_ts:
|
||||
self.irc.applyModes(channel, [('+%s' % mode, user) for mode in modeprefix])
|
||||
|
||||
# Only save mode changes if the remote has lower TS than us.
|
||||
changedmodes |= {('+%s' % mode, user) for mode in modeprefix}
|
||||
|
||||
self.irc.channels[channel].users.add(user)
|
||||
|
||||
# Statekeeping with timestamps
|
||||
their_ts = int(args[1])
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
self.updateTS(channel, their_ts, changedmodes, outbound=False)
|
||||
|
||||
return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts}
|
||||
|
||||
def handle_uid(self, numeric, command, args):
|
||||
|
@ -938,10 +938,6 @@ class P10Protocol(Protocol):
|
||||
|
||||
channel = self.irc.toLower(args[0])
|
||||
userlist = args[-1].split()
|
||||
their_ts = int(args[1])
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
|
||||
self.updateTS(channel, their_ts)
|
||||
|
||||
bans = []
|
||||
if args[-1].startswith('%'):
|
||||
@ -972,6 +968,9 @@ class P10Protocol(Protocol):
|
||||
else:
|
||||
parsedmodes = []
|
||||
|
||||
# Keep track of other modes that are added due to prefix modes being joined too.
|
||||
changedmodes = set(parsedmodes)
|
||||
|
||||
# Add the ban list to the list of modes to process.
|
||||
parsedmodes.extend(bans)
|
||||
|
||||
@ -1006,11 +1005,16 @@ class P10Protocol(Protocol):
|
||||
|
||||
self.irc.users[user].channels.add(channel)
|
||||
|
||||
if their_ts <= our_ts:
|
||||
self.irc.applyModes(channel, [('+%s' % mode, user) for mode in prefixes])
|
||||
# Only save mode changes if the remote has lower TS than us.
|
||||
changedmodes |= {('+%s' % mode, user) for mode in prefixes}
|
||||
|
||||
self.irc.channels[channel].users.add(user)
|
||||
|
||||
# Statekeeping with timestamps
|
||||
their_ts = int(args[1])
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
self.updateTS(channel, their_ts, changedmodes, outbound=False)
|
||||
|
||||
return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts}
|
||||
|
||||
def handle_join(self, source, command, args):
|
||||
|
@ -436,15 +436,15 @@ class TS6Protocol(TS6BaseProtocol):
|
||||
# <- :0UY SJOIN 1451041566 #channel +nt :@0UYAAAAAB
|
||||
channel = self.irc.toLower(args[1])
|
||||
userlist = args[-1].split()
|
||||
their_ts = int(args[0])
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
|
||||
self.updateTS(channel, their_ts)
|
||||
|
||||
modestring = args[2:-1] or args[2]
|
||||
parsedmodes = self.irc.parseModes(channel, modestring)
|
||||
self.irc.applyModes(channel, parsedmodes)
|
||||
namelist = []
|
||||
|
||||
# Keep track of other modes that are added due to prefix modes being joined too.
|
||||
changedmodes = set(parsedmodes)
|
||||
|
||||
log.debug('(%s) handle_sjoin: got userlist %r for %r', self.irc.name, userlist, channel)
|
||||
for userpair in userlist:
|
||||
# charybdis sends this in the form "@+UID1, +UID2, UID3, @UID4"
|
||||
@ -469,9 +469,16 @@ class TS6Protocol(TS6BaseProtocol):
|
||||
finalprefix += char
|
||||
namelist.append(user)
|
||||
self.irc.users[user].channels.add(channel)
|
||||
if their_ts <= our_ts:
|
||||
self.irc.applyModes(channel, [('+%s' % mode, user) for mode in finalprefix])
|
||||
|
||||
# Only save mode changes if the remote has lower TS than us.
|
||||
changedmodes |= {('+%s' % mode, user) for mode in finalprefix}
|
||||
self.irc.channels[channel].users.add(user)
|
||||
|
||||
# Statekeeping with timestamps
|
||||
their_ts = int(args[0])
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
self.updateTS(channel, their_ts, changedmodes, outbound=False)
|
||||
|
||||
return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts}
|
||||
|
||||
def handle_join(self, numeric, command, args):
|
||||
|
@ -556,12 +556,12 @@ class UnrealProtocol(TS6BaseProtocol):
|
||||
channel = self.irc.toLower(args[1])
|
||||
userlist = args[-1].split()
|
||||
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
their_ts = int(args[0])
|
||||
self.updateTS(channel, their_ts)
|
||||
|
||||
namelist = []
|
||||
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.
|
||||
changedmodes = set(self.irc.channels[channel].modes)
|
||||
|
||||
for userpair in userlist:
|
||||
if userpair.startswith("&\"'"): # TODO: handle ban bursts too
|
||||
# &, ", and ' entries are used for bursting bans:
|
||||
@ -583,10 +583,16 @@ class UnrealProtocol(TS6BaseProtocol):
|
||||
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.
|
||||
if their_ts <= our_ts:
|
||||
self.irc.applyModes(channel, [('+%s' % mode, user) for mode in finalprefix])
|
||||
changedmodes |= {('+%s' % mode, user) for mode in finalprefix}
|
||||
|
||||
self.irc.channels[channel].users.add(user)
|
||||
|
||||
our_ts = self.irc.channels[channel].ts
|
||||
their_ts = int(args[0])
|
||||
self.updateTS(channel, their_ts, changedmodes, outbound=False)
|
||||
|
||||
return {'channel': channel, 'users': namelist, 'modes': self.irc.channels[channel].modes, 'ts': their_ts}
|
||||
|
||||
def handle_nick(self, numeric, command, args):
|
||||
|
Loading…
Reference in New Issue
Block a user