3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-12-24 11:42:51 +01:00

core: define two (joined) versions of the channels index

Closes #509.

PyLinkNetworkCore.channels is split into the following:
- irc._channels which implicitly creates channels on access (mostly used in protocol modules)
- irc.channels which does not (recommended for use by plugins)
This commit is contained in:
James Lu 2017-08-25 02:11:48 -07:00
parent f34198647e
commit 80766e051e
9 changed files with 137 additions and 132 deletions

View File

@ -130,11 +130,16 @@ class PyLinkNetworkCore(utils.DeprecatedAttributesObject, utils.CamelCaseToSnake
self.called_in = None self.called_in = None
# Intialize the server, channel, and user indexes to be populated by # Intialize the server, channel, and user indexes to be populated by
# our protocol module. For the server index, we can add ourselves right # our protocol module.
# now.
self.servers = {} self.servers = {}
self.users = {} self.users = {}
self.channels = ChannelState(self)
# Two versions of the channels index exist in PyLink 2.0, and they are joined together
# - irc._channels which implicitly creates channels on access (mostly used
# in protocol modules)
# - irc.channels which does not (recommended for use by plugins)
self._channels = ChannelState(self)
self.channels = structures.IRCCaseInsensitiveDict(self, data=self._channels._data)
# This sets the list of supported channel and user modes: the default # This sets the list of supported channel and user modes: the default
# RFC1459 modes are implied. Named modes are used here to make # RFC1459 modes are implied. Named modes are used here to make
@ -531,7 +536,7 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
log.debug('(%s) Using self.cmodes for this query: %s', self.name, self.cmodes) log.debug('(%s) Using self.cmodes for this query: %s', self.name, self.cmodes)
supported_modes = self.cmodes supported_modes = self.cmodes
oldmodes = self.channels[target].modes oldmodes = self._channels[target].modes
res = [] res = []
for mode in modestring: for mode in modestring:
if mode in '+-': if mode in '+-':
@ -601,7 +606,7 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
old_modelist = self.users[target].modes old_modelist = self.users[target].modes
supported_modes = self.umodes supported_modes = self.umodes
else: else:
old_modelist = self.channels[target].modes old_modelist = self._channels[target].modes
supported_modes = self.cmodes supported_modes = self.cmodes
except KeyError: except KeyError:
log.warning('(%s) Possible desync? Mode target %s is unknown.', self.name, target) log.warning('(%s) Possible desync? Mode target %s is unknown.', self.name, target)
@ -621,7 +626,7 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
# if the IRCd supports this mode and it is the one being set, add/remove # if the IRCd supports this mode and it is the one being set, add/remove
# the person from the corresponding prefix mode list (e.g. c.prefixmodes['op'] # the person from the corresponding prefix mode list (e.g. c.prefixmodes['op']
# for ops). # for ops).
for pmode, pmodelist in self.channels[target].prefixmodes.items(): for pmode, pmodelist in self._channels[target].prefixmodes.items():
if pmode in self.cmodes and real_mode[0] == self.cmodes[pmode]: if pmode in self.cmodes and real_mode[0] == self.cmodes[pmode]:
log.debug('(%s) Initial prefixmodes list: %s', self.name, pmodelist) log.debug('(%s) Initial prefixmodes list: %s', self.name, pmodelist)
if mode[0][0] == '+': if mode[0][0] == '+':
@ -668,7 +673,7 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
if usermodes: if usermodes:
self.users[target].modes = modelist self.users[target].modes = modelist
else: else:
self.channels[target].modes = modelist self._channels[target].modes = modelist
except KeyError: except KeyError:
log.warning("(%s) Invalid MODE target %s (usermodes=%s)", self.name, target, usermodes) log.warning("(%s) Invalid MODE target %s (usermodes=%s)", self.name, target, usermodes)
@ -706,7 +711,7 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
modes = self.parse_modes(target, modes.split(" ")) modes = self.parse_modes(target, modes.split(" "))
# Get the current mode list first. # Get the current mode list first.
if utils.isChannel(target): if utils.isChannel(target):
c = oldobj or self.channels[target] c = oldobj or self._channels[target]
oldmodes = c.modes.copy() oldmodes = c.modes.copy()
possible_modes = self.cmodes.copy() possible_modes = self.cmodes.copy()
# For channels, this also includes the list of prefix modes. # For channels, this also includes the list of prefix modes.
@ -1116,8 +1121,8 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
def _clear(): def _clear():
log.debug("(%s) Clearing local modes from channel %s due to TS change", self.name, log.debug("(%s) Clearing local modes from channel %s due to TS change", self.name,
channel) channel)
self.channels[channel].modes.clear() self._channels[channel].modes.clear()
for p in self.channels[channel].prefixmodes.values(): for p in self._channels[channel].prefixmodes.values():
for user in p.copy(): for user in p.copy():
if not self.is_internal_client(user): if not self.is_internal_client(user):
p.discard(user) p.discard(user)
@ -1131,7 +1136,7 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
# Use a lock so only one thread can change a channel's TS at once: this prevents race # Use a lock so only one thread can change a channel's TS at once: this prevents race
# conditions that would otherwise desync channel modes. # conditions that would otherwise desync channel modes.
with self._ts_lock: with self._ts_lock:
our_ts = self.channels[channel].ts our_ts = self._channels[channel].ts
assert isinstance(our_ts, int), "Wrong type for our_ts (expected int, got %s)" % type(our_ts) assert isinstance(our_ts, int), "Wrong type for our_ts (expected int, got %s)" % type(our_ts)
assert isinstance(their_ts, int), "Wrong type for their_ts (expected int, got %s)" % type(their_ts) assert isinstance(their_ts, int), "Wrong type for their_ts (expected int, got %s)" % type(their_ts)
@ -1153,7 +1158,7 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
else: else:
log.debug('(%s) Resetting channel TS of %s from %s to %s (remote has lower TS)', log.debug('(%s) Resetting channel TS of %s from %s to %s (remote has lower TS)',
self.name, channel, our_ts, their_ts) self.name, channel, our_ts, their_ts)
self.channels[channel].ts = their_ts self._channels[channel].ts = their_ts
# Remote TS was lower and we're receiving modes. Clear the modelist and apply theirs. # Remote TS was lower and we're receiving modes. Clear the modelist and apply theirs.

View File

@ -168,7 +168,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
if self.pseudoclient and client == self.pseudoclient.uid: if self.pseudoclient and client == self.pseudoclient.uid:
self.send('JOIN %s' % channel) self.send('JOIN %s' % channel)
else: else:
self.channels[channel].users.add(client) self._channels[channel].users.add(client)
self.users[client].channels.add(channel) self.users[client].channels.add(channel)
log.debug('(%s) join: faking JOIN of client %s/%s to %s', self.name, client, log.debug('(%s) join: faking JOIN of client %s/%s to %s', self.name, client,
@ -272,7 +272,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
def part(self, source, channel, reason=''): def part(self, source, channel, reason=''):
"""STUB: Parts a user from a channel.""" """STUB: Parts a user from a channel."""
self.channels[channel].remove_user(source) self._channels[channel].remove_user(source)
self.users[source].channels.discard(channel) self.users[source].channels.discard(channel)
# Only parts for the main PyLink client are actually forwarded. Others are ignored. # Only parts for the main PyLink client are actually forwarded. Others are ignored.
@ -300,7 +300,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
# Otherwise, track the state for our virtual clients. # Otherwise, track the state for our virtual clients.
self.users[user].channels.add(channel) self.users[user].channels.add(channel)
self.channels[channel].users |= puids self._channels[channel].users |= puids
nicks = {self.get_friendly_name(u) for u in puids} nicks = {self.get_friendly_name(u) for u in puids}
self.call_hooks([server, 'CLIENTBOT_SJOIN', {'channel': channel, 'nicks': nicks}]) self.call_hooks([server, 'CLIENTBOT_SJOIN', {'channel': channel, 'nicks': nicks}])
@ -671,7 +671,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
# Queue these virtual users to be joined if they're not already in the channel, # Queue these virtual users to be joined if they're not already in the channel,
# or we're waiting for a kick acknowledgment for them. # or we're waiting for a kick acknowledgment for them.
if (idsource not in self.channels[channel].users) or (idsource in \ if (idsource not in self._channels[channel].users) or (idsource in \
self.kick_queue.get(channel, ([],))[0]): self.kick_queue.get(channel, ([],))[0]):
names.add(idsource) names.add(idsource)
self.users[idsource].channels.add(channel) self.users[idsource].channels.add(channel)
@ -686,7 +686,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
break break
# Statekeeping: make sure the channel's user list is updated! # Statekeeping: make sure the channel's user list is updated!
self.channels[channel].users |= names self._channels[channel].users |= names
self.apply_modes(channel, modes) self.apply_modes(channel, modes)
log.debug('(%s) handle_353: adding users %s to %s', self.name, names, channel) log.debug('(%s) handle_353: adding users %s to %s', self.name, names, channel)
@ -698,7 +698,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
fully_synced_names = [uid for uid in names if hasattr(self.users[uid], '_clientbot_identhost_received')] fully_synced_names = [uid for uid in names if hasattr(self.users[uid], '_clientbot_identhost_received')]
if fully_synced_names: if fully_synced_names:
log.debug('(%s) handle_353: sending pre-WHO JOIN hook for %s: %s', self.name, channel, fully_synced_names) log.debug('(%s) handle_353: sending pre-WHO JOIN hook for %s: %s', self.name, channel, fully_synced_names)
return {'channel': channel, 'users': fully_synced_names, 'modes': self.channels[channel].modes, return {'channel': channel, 'users': fully_synced_names, 'modes': self._channels[channel].modes,
'parse_as': "JOIN"} 'parse_as': "JOIN"}
def _check_puid_collision(self, nick): def _check_puid_collision(self, nick):
@ -796,7 +796,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
self.who_received.clear() self.who_received.clear()
channel = args[1] channel = args[1]
c = self.channels[channel] c = self._channels[channel]
modes = set(c.modes) modes = set(c.modes)
for user in users.copy(): for user in users.copy():
@ -848,7 +848,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
# With extended-join: # With extended-join:
# <- :GL|!~GL@127.0.0.1 JOIN #whatever accountname :realname # <- :GL|!~GL@127.0.0.1 JOIN #whatever accountname :realname
channel = args[0] channel = args[0]
self.channels[channel].users.add(source) self._channels[channel].users.add(source)
self.users[source].channels.add(channel) self.users[source].channels.add(channel)
if len(args) >= 3: if len(args) >= 3:
@ -864,7 +864,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
self._send_who(channel) self._send_who(channel)
else: else:
self.call_hooks([source, 'CLIENTBOT_JOIN', {'channel': channel}]) self.call_hooks([source, 'CLIENTBOT_JOIN', {'channel': channel}])
return {'channel': channel, 'users': [source], 'modes': self.channels[channel].modes} return {'channel': channel, 'users': [source], 'modes': self._channels[channel].modes}
def handle_kick(self, source, command, args): def handle_kick(self, source, command, args):
""" """
@ -891,7 +891,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
del self.kick_queue[channel] del self.kick_queue[channel]
# Statekeeping: remove the target from the channel they were previously in. # Statekeeping: remove the target from the channel they were previously in.
self.channels[channel].remove_user(target) self._channels[channel].remove_user(target)
try: try:
self.users[target].channels.remove(channel) self.users[target].channels.remove(channel)
except KeyError: except KeyError:
@ -903,7 +903,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
# Delete channels that we were kicked from, for better state keeping. # Delete channels that we were kicked from, for better state keeping.
if self.pseudoclient and target == self.pseudoclient.uid: if self.pseudoclient and target == self.pseudoclient.uid:
del self.channels[channel] del self._channels[channel]
def handle_mode(self, source, command, args): def handle_mode(self, source, command, args):
"""Handles MODE changes.""" """Handles MODE changes."""
@ -911,7 +911,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
# <- :ice MODE ice :+Zi # <- :ice MODE ice :+Zi
target = args[0] target = args[0]
if utils.isChannel(target): if utils.isChannel(target):
oldobj = self.channels[target].deepcopy() oldobj = self._channels[target].deepcopy()
else: else:
target = self.nick_to_uid(target) target = self.nick_to_uid(target)
oldobj = None oldobj = None
@ -944,7 +944,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
"""Handles TS announcements via RPL_CREATIONTIME.""" """Handles TS announcements via RPL_CREATIONTIME."""
channel = args[1] channel = args[1]
ts = int(args[2]) ts = int(args[2])
self.channels[channel].ts = ts self._channels[channel].ts = ts
def handle_chghost(self, source, command, args): def handle_chghost(self, source, command, args):
"""Handles the IRCv3 CHGHOST command.""" """Handles the IRCv3 CHGHOST command."""
@ -995,15 +995,15 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
reason = '' reason = ''
for channel in channels: for channel in channels:
self.channels[channel].remove_user(source) self._channels[channel].remove_user(source)
self.users[source].channels -= set(channels) self.users[source].channels -= set(channels)
self.call_hooks([source, 'PART', {'channels': channels, 'text': reason}]) self.call_hooks([source, 'PART', {'channels': channels, 'text': reason}])
# Clear channels that are empty, or that we're parting. # Clear channels that are empty, or that we're parting.
for channel in channels: for channel in channels:
if (self.pseudoclient and source == self.pseudoclient.uid) or not self.channels[channel].users: if (self.pseudoclient and source == self.pseudoclient.uid) or not self._channels[channel].users:
del self.channels[channel] del self._channels[channel]
def handle_ping(self, source, command, args): def handle_ping(self, source, command, args):
""" """

View File

@ -162,12 +162,12 @@ class HybridProtocol(TS6Protocol):
if not self.is_internal_server(numeric): if not self.is_internal_server(numeric):
raise LookupError('No such PyLink server exists.') raise LookupError('No such PyLink server exists.')
ts = self.channels[target].ts ts = self._channels[target].ts
servername = self.servers[numeric].name servername = self.servers[numeric].name
self._send_with_prefix(numeric, 'TBURST %s %s %s %s :%s' % (ts, target, int(time.time()), servername, text)) self._send_with_prefix(numeric, 'TBURST %s %s %s %s :%s' % (ts, target, int(time.time()), servername, text))
self.channels[target].topic = text self._channels[target].topic = text
self.channels[target].topicset = True self._channels[target].topicset = True
# command handlers # command handlers
@ -221,8 +221,8 @@ class HybridProtocol(TS6Protocol):
ts = args[2] ts = args[2]
setter = args[3] setter = args[3]
topic = args[-1] topic = args[-1]
self.channels[channel].topic = topic self._channels[channel].topic = topic
self.channels[channel].topicset = True self._channels[channel].topicset = True
return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic} return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic}
def handle_eob(self, numeric, command, args): def handle_eob(self, numeric, command, args):

View File

@ -83,11 +83,11 @@ class InspIRCdProtocol(TS6BaseProtocol):
raise LookupError('No such PyLink client exists.') raise LookupError('No such PyLink client exists.')
# Strip out list-modes, they shouldn't be ever sent in FJOIN. # Strip out list-modes, they shouldn't be ever sent in FJOIN.
modes = [m for m in self.channels[channel].modes if m[0] not in self.cmodes['*A']] modes = [m for m in self._channels[channel].modes if m[0] not in self.cmodes['*A']]
self._send_with_prefix(server, "FJOIN {channel} {ts} {modes} :,{uid}".format( self._send_with_prefix(server, "FJOIN {channel} {ts} {modes} :,{uid}".format(
ts=self.channels[channel].ts, uid=client, channel=channel, ts=self._channels[channel].ts, uid=client, channel=channel,
modes=self.join_modes(modes))) modes=self.join_modes(modes)))
self.channels[channel].users.add(client) self._channels[channel].users.add(client)
self.users[client].channels.add(channel) self.users[client].channels.add(channel)
def sjoin(self, server, channel, users, ts=None, modes=set()): def sjoin(self, server, channel, users, ts=None, modes=set()):
@ -109,8 +109,8 @@ class InspIRCdProtocol(TS6BaseProtocol):
raise LookupError('No such PyLink client exists.') raise LookupError('No such PyLink client exists.')
# Strip out list-modes, they shouldn't ever be sent in FJOIN (protocol rules). # Strip out list-modes, they shouldn't ever be sent in FJOIN (protocol rules).
modes = modes or self.channels[channel].modes modes = modes or self._channels[channel].modes
orig_ts = self.channels[channel].ts orig_ts = self._channels[channel].ts
ts = ts or orig_ts ts = ts or orig_ts
banmodes = [] banmodes = []
@ -120,7 +120,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
if modechar in self.cmodes['*A']: if modechar in self.cmodes['*A']:
# Track bans separately (they are sent as a normal FMODE instead of in FJOIN. # Track bans separately (they are sent as a normal FMODE instead of in FJOIN.
# However, don't reset bans that have already been set. # However, don't reset bans that have already been set.
if (modechar, mode[1]) not in self.channels[channel].modes: if (modechar, mode[1]) not in self._channels[channel].modes:
banmodes.append(mode) banmodes.append(mode)
else: else:
regularmodes.append(mode) regularmodes.append(mode)
@ -146,7 +146,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
self._send_with_prefix(server, "FJOIN {channel} {ts} {modes} :{users}".format( self._send_with_prefix(server, "FJOIN {channel} {ts} {modes} :{users}".format(
ts=ts, users=namelist, channel=channel, ts=ts, users=namelist, channel=channel,
modes=self.join_modes(modes))) modes=self.join_modes(modes)))
self.channels[channel].users.update(uids) self._channels[channel].users.update(uids)
if banmodes: if banmodes:
# Burst ban modes if there are any. # Burst ban modes if there are any.
@ -207,7 +207,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
self.apply_modes(target, modes) self.apply_modes(target, modes)
joinedmodes = self.join_modes(modes) joinedmodes = self.join_modes(modes)
if utils.isChannel(target): if utils.isChannel(target):
ts = ts or self.channels[target].ts ts = ts or self._channels[target].ts
self._send_with_prefix(numeric, 'FMODE %s %s %s' % (target, ts, joinedmodes)) self._send_with_prefix(numeric, 'FMODE %s %s %s' % (target, ts, joinedmodes))
else: else:
self._send_with_prefix(numeric, 'MODE %s %s' % (target, joinedmodes)) self._send_with_prefix(numeric, 'MODE %s %s' % (target, joinedmodes))
@ -241,8 +241,8 @@ class InspIRCdProtocol(TS6BaseProtocol):
ts = int(time.time()) ts = int(time.time())
servername = self.servers[numeric].name servername = self.servers[numeric].name
self._send_with_prefix(numeric, 'FTOPIC %s %s %s :%s' % (target, ts, servername, text)) self._send_with_prefix(numeric, 'FTOPIC %s %s %s :%s' % (target, ts, servername, text))
self.channels[target].topic = text self._channels[target].topic = text
self.channels[target].topicset = True self._channels[target].topicset = True
def knock(self, numeric, target, text): def knock(self, numeric, target, text):
"""Sends a KNOCK from a PyLink client.""" """Sends a KNOCK from a PyLink client."""
@ -539,7 +539,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
"""Handles incoming FJOIN commands (InspIRCd equivalent of JOIN/SJOIN).""" """Handles incoming FJOIN commands (InspIRCd equivalent of JOIN/SJOIN)."""
# :70M FJOIN #chat 1423790411 +AFPfjnt 6:5 7:5 9:5 :o,1SRAABIT4 v,1IOAAF53R <...> # :70M FJOIN #chat 1423790411 +AFPfjnt 6:5 7:5 9:5 :o,1SRAABIT4 v,1IOAAF53R <...>
channel = args[0] channel = args[0]
chandata = self.channels[channel].deepcopy() chandata = self._channels[channel].deepcopy()
# InspIRCd sends each channel's users in the form of 'modeprefix(es),UID' # InspIRCd sends each channel's users in the form of 'modeprefix(es),UID'
userlist = args[-1].split() userlist = args[-1].split()
@ -565,7 +565,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
# Only save mode changes if the remote has lower TS than us. # Only save mode changes if the remote has lower TS than us.
changedmodes |= {('+%s' % mode, user) for mode in modeprefix} changedmodes |= {('+%s' % mode, user) for mode in modeprefix}
self.channels[channel].users.add(user) self._channels[channel].users.add(user)
# Statekeeping with timestamps. Note: some service packages (Anope 1.8) send a trailing # Statekeeping with timestamps. Note: some service packages (Anope 1.8) send a trailing
# 'd' after the timestamp, which we should strip out to prevent int() from erroring. # 'd' after the timestamp, which we should strip out to prevent int() from erroring.
@ -574,7 +574,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
# <- :3AX FJOIN #monitor 1485462109d + :,3AXAAAAAK # <- :3AX FJOIN #monitor 1485462109d + :,3AXAAAAAK
their_ts = int(''.join(char for char in args[1] if char.isdigit())) their_ts = int(''.join(char for char in args[1] if char.isdigit()))
our_ts = self.channels[channel].ts our_ts = self._channels[channel].ts
self.updateTS(servernumeric, channel, their_ts, changedmodes) self.updateTS(servernumeric, channel, their_ts, changedmodes)
return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts, return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts,
@ -627,7 +627,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
"""Handles the FMODE command, used for channel mode changes.""" """Handles the FMODE command, used for channel mode changes."""
# <- :70MAAAAAA FMODE #chat 1433653462 +hhT 70MAAAAAA 70MAAAAAD # <- :70MAAAAAA FMODE #chat 1433653462 +hhT 70MAAAAAA 70MAAAAAD
channel = args[0] channel = args[0]
oldobj = self.channels[channel].deepcopy() oldobj = self._channels[channel].deepcopy()
modes = args[2:] modes = args[2:]
changedmodes = self.parse_modes(channel, modes) changedmodes = self.parse_modes(channel, modes)
self.apply_modes(channel, changedmodes) self.apply_modes(channel, changedmodes)
@ -661,8 +661,8 @@ class InspIRCdProtocol(TS6BaseProtocol):
ts = args[1] ts = args[1]
setter = args[2] setter = args[2]
topic = args[-1] topic = args[-1]
self.channels[channel].topic = topic self._channels[channel].topic = topic
self.channels[channel].topicset = True self._channels[channel].topicset = True
return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic} return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic}
# SVSTOPIC is used by InspIRCd module m_topiclock - its arguments are the same as FTOPIC # SVSTOPIC is used by InspIRCd module m_topiclock - its arguments are the same as FTOPIC

View File

@ -110,7 +110,7 @@ class IRCCommonProtocol(IRCNetwork):
# Prevent RuntimeError: dictionary changed size during iteration # Prevent RuntimeError: dictionary changed size during iteration
old_servers = self.servers.copy() old_servers = self.servers.copy()
old_channels = self.channels.copy() old_channels = self._channels.copy()
# Cycle through our list of servers. If any server's uplink is the one that is being SQUIT, # Cycle through our list of servers. If any server's uplink is the one that is being SQUIT,
# remove them and all their users too. # remove them and all their users too.
@ -468,8 +468,8 @@ class IRCS2SProtocol(IRCCommonProtocol):
raise LookupError('No such PyLink client/server exists.') raise LookupError('No such PyLink client/server exists.')
self._send_with_prefix(source, 'TOPIC %s :%s' % (target, text)) self._send_with_prefix(source, 'TOPIC %s :%s' % (target, text))
self.channels[target].topic = text self._channels[target].topic = text
self.channels[target].topicset = True self._channels[target].topicset = True
topic_burst = topic topic_burst = topic
def handle_invite(self, numeric, command, args): def handle_invite(self, numeric, command, args):
@ -590,7 +590,7 @@ class IRCS2SProtocol(IRCCommonProtocol):
# <- ABAAA OM #test +h ABAAA # <- ABAAA OM #test +h ABAAA
target = self._get_UID(args[0]) target = self._get_UID(args[0])
if utils.isChannel(target): if utils.isChannel(target):
channeldata = self.channels[target].deepcopy() channeldata = self._channels[target].deepcopy()
else: else:
channeldata = None channeldata = None
@ -611,11 +611,11 @@ class IRCS2SProtocol(IRCCommonProtocol):
channels = args[0].split(',') channels = args[0].split(',')
for channel in channels.copy(): for channel in channels.copy():
if channel not in self.channels or source not in self.channels[channel].users: if channel not in self._channels or source not in self._channels[channel].users:
# Ignore channels the user isn't on, and remove them from any hook payloads. # Ignore channels the user isn't on, and remove them from any hook payloads.
channels.remove(channel) channels.remove(channel)
self.channels[channel].remove_user(source) self._channels[channel].remove_user(source)
try: try:
self.users[source].channels.discard(channel) self.users[source].channels.discard(channel)
except KeyError: except KeyError:
@ -627,8 +627,8 @@ class IRCS2SProtocol(IRCCommonProtocol):
reason = '' reason = ''
# Clear empty non-permanent channels. # Clear empty non-permanent channels.
if not (self.channels[channel].users or ((self.cmodes.get('permanent'), None) in self.channels[channel].modes)): if not (self._channels[channel].users or ((self.cmodes.get('permanent'), None) in self._channels[channel].modes)):
del self.channels[channel] del self._channels[channel]
if channels: if channels:
return {'channels': channels, 'text': reason} return {'channels': channels, 'text': reason}
@ -685,9 +685,9 @@ class IRCS2SProtocol(IRCCommonProtocol):
channel = args[0] channel = args[0]
topic = args[1] topic = args[1]
oldtopic = self.channels[channel].topic oldtopic = self._channels[channel].topic
self.channels[channel].topic = topic self._channels[channel].topic = topic
self.channels[channel].topicset = True self._channels[channel].topicset = True
return {'channel': channel, 'setter': numeric, 'text': topic, return {'channel': channel, 'setter': numeric, 'text': topic,
'oldtopic': oldtopic} 'oldtopic': oldtopic}

View File

@ -154,7 +154,7 @@ class NgIRCdProtocol(IRCS2SProtocol):
raise LookupError('No such PyLink client exists.') raise LookupError('No such PyLink client exists.')
self._send_with_prefix(client, "JOIN %s" % channel) self._send_with_prefix(client, "JOIN %s" % channel)
self.channels[channel].users.add(client) self._channels[channel].users.add(client)
self.users[client].channels.add(channel) self.users[client].channels.add(channel)
def kill(self, source, target, reason): def kill(self, source, target, reason):
@ -241,7 +241,7 @@ class NgIRCdProtocol(IRCS2SProtocol):
# Add the affected users to our state. # Add the affected users to our state.
for userpair in users: for userpair in users:
uid = userpair[1] uid = userpair[1]
self.channels[channel].users.add(uid) self._channels[channel].users.add(uid)
try: try:
self.users[uid].channels.add(channel) self.users[uid].channels.add(channel)
except KeyError: # Not initialized yet? except KeyError: # Not initialized yet?
@ -337,8 +337,8 @@ class NgIRCdProtocol(IRCS2SProtocol):
topic = args[-1] topic = args[-1]
if topic: if topic:
log.debug('(%s) handle_chaninfo: setting topic for %s to %r', self.name, channel, topic) log.debug('(%s) handle_chaninfo: setting topic for %s to %r', self.name, channel, topic)
self.channels[channel].topic = topic self._channels[channel].topic = topic
self.channels[channel].topicset = True self._channels[channel].topicset = True
if len(args) >= 5: if len(args) >= 5:
key = args[2] key = args[2]
@ -364,10 +364,10 @@ class NgIRCdProtocol(IRCS2SProtocol):
except ValueError: except ValueError:
channel = chanpair channel = chanpair
c = self.channels[channel] c = self._channels[channel]
self.users[source].channels.add(channel) self.users[source].channels.add(channel)
self.channels[channel].users.add(source) self._channels[channel].users.add(source)
# Call hooks manually, because one JOIN command have multiple channels. # Call hooks manually, because one JOIN command have multiple channels.
self.call_hooks([source, command, {'channel': channel, 'users': [source], 'modes': c.modes}]) self.call_hooks([source, command, {'channel': channel, 'users': [source], 'modes': c.modes}])
@ -469,7 +469,7 @@ class NgIRCdProtocol(IRCS2SProtocol):
# <- :ngircd.midnight.local NJOIN #test :tester,@%GL # <- :ngircd.midnight.local NJOIN #test :tester,@%GL
channel = args[0] channel = args[0]
chandata = self.channels[channel].deepcopy() chandata = self._channels[channel].deepcopy()
namelist = [] namelist = []
# Reverse the modechar->modeprefix mapping for quicker lookup # Reverse the modechar->modeprefix mapping for quicker lookup
@ -487,7 +487,7 @@ class NgIRCdProtocol(IRCS2SProtocol):
# Final bits of state tracking. (I hate having to do this everywhere...) # Final bits of state tracking. (I hate having to do this everywhere...)
self.users[user].channels.add(channel) self.users[user].channels.add(channel)
self.channels[channel].users.add(user) self._channels[channel].users.add(user)
return {'channel': channel, 'users': namelist, 'modes': [], 'channeldata': chandata} return {'channel': channel, 'users': namelist, 'modes': [], 'channeldata': chandata}

View File

@ -322,23 +322,23 @@ class P10Protocol(IRCS2SProtocol):
nick = self.users[target].nick nick = self.users[target].nick
self._send_with_prefix(numeric, 'I %s %s %s' % (nick, channel, self.channels[channel].ts)) self._send_with_prefix(numeric, 'I %s %s %s' % (nick, channel, self._channels[channel].ts))
def join(self, client, channel): def join(self, client, channel):
"""Joins a PyLink client to a channel.""" """Joins a PyLink client to a channel."""
# <- ABAAB J #test3 1460744371 # <- ABAAB J #test3 1460744371
ts = self.channels[channel].ts ts = self._channels[channel].ts
if not self.is_internal_client(client): if not self.is_internal_client(client):
raise LookupError('No such PyLink client exists.') raise LookupError('No such PyLink client exists.')
if not self.channels[channel].users: if not self._channels[channel].users:
# Empty channels should be created with the CREATE command. # Empty channels should be created with the CREATE command.
self._send_with_prefix(client, "C {channel} {ts}".format(ts=ts, channel=channel)) self._send_with_prefix(client, "C {channel} {ts}".format(ts=ts, channel=channel))
else: else:
self._send_with_prefix(client, "J {channel} {ts}".format(ts=ts, channel=channel)) self._send_with_prefix(client, "J {channel} {ts}".format(ts=ts, channel=channel))
self.channels[channel].users.add(client) self._channels[channel].users.add(client)
self.users[client].channels.add(channel) self.users[client].channels.add(channel)
def kick(self, numeric, channel, target, reason=None): def kick(self, numeric, channel, target, reason=None):
@ -351,7 +351,7 @@ class P10Protocol(IRCS2SProtocol):
if not reason: if not reason:
reason = 'No reason given' reason = 'No reason given'
cobj = self.channels[channel] cobj = self._channels[channel]
# Prevent kick bounces by sending our kick through the server if # Prevent kick bounces by sending our kick through the server if
# the sender isn't op. # the sender isn't op.
if numeric not in self.servers and (not cobj.is_halfop_plus(numeric)): if numeric not in self.servers and (not cobj.is_halfop_plus(numeric)):
@ -409,7 +409,7 @@ class P10Protocol(IRCS2SProtocol):
is_cmode = utils.isChannel(target) is_cmode = utils.isChannel(target)
if is_cmode: if is_cmode:
# Channel mode changes have a trailing TS. User mode changes do not. # Channel mode changes have a trailing TS. User mode changes do not.
cobj = self.channels[target] cobj = self._channels[target]
ts = ts or cobj.ts ts = ts or cobj.ts
# Prevent mode bounces by sending our mode through the server if # Prevent mode bounces by sending our mode through the server if
@ -530,8 +530,8 @@ class P10Protocol(IRCS2SProtocol):
# <- AB B #test 1460742014 +tnl 10 ABAAB,ABAAA:o :%*!*@other.bad.host *!*@bad.host # <- AB B #test 1460742014 +tnl 10 ABAAB,ABAAA:o :%*!*@other.bad.host *!*@bad.host
# <- AB B #test2 1460743539 +l 10 ABAAA:vo :%*!*@bad.host # <- AB B #test2 1460743539 +l 10 ABAAA:vo :%*!*@bad.host
# <- AB B #test 1460747615 ABAAA:o :% ~ *!*@test.host # <- AB B #test 1460747615 ABAAA:o :% ~ *!*@test.host
modes = modes or self.channels[channel].modes modes = modes or self._channels[channel].modes
orig_ts = self.channels[channel].ts orig_ts = self._channels[channel].ts
ts = ts or orig_ts ts = ts or orig_ts
bans = [] bans = []
@ -541,7 +541,7 @@ class P10Protocol(IRCS2SProtocol):
modechar = mode[0][-1] modechar = mode[0][-1]
# Store bans and exempts in separate lists for processing, but don't reset bans that have already been set. # Store bans and exempts in separate lists for processing, but don't reset bans that have already been set.
if modechar in self.cmodes['*A']: if modechar in self.cmodes['*A']:
if (modechar, mode[1]) not in self.channels[channel].modes: if (modechar, mode[1]) not in self._channels[channel].modes:
if modechar == 'b': if modechar == 'b':
bans.append(mode[1]) bans.append(mode[1])
elif modechar == 'e': elif modechar == 'e':
@ -624,7 +624,7 @@ class P10Protocol(IRCS2SProtocol):
self.send(wrapped_msg) self.send(wrapped_msg)
self.channels[channel].users.update(changedusers) self._channels[channel].users.update(changedusers)
# Technically we can send bans together with the above user introductions, but # Technically we can send bans together with the above user introductions, but
# it's easier to line wrap them separately. # it's easier to line wrap them separately.
@ -699,12 +699,12 @@ class P10Protocol(IRCS2SProtocol):
# For servers, just show the server name. # For servers, just show the server name.
sendername = self.get_friendly_name(source) sendername = self.get_friendly_name(source)
creationts = self.channels[target].ts creationts = self._channels[target].ts
self._send_with_prefix(source, 'T %s %s %s %s :%s' % (target, sendername, creationts, self._send_with_prefix(source, 'T %s %s %s %s :%s' % (target, sendername, creationts,
int(time.time()), text)) int(time.time()), text))
self.channels[target].topic = text self._channels[target].topic = text
self.channels[target].topicset = True self._channels[target].topicset = True
topic_burst = topic topic_burst = topic
def update_client(self, target, field, text): def update_client(self, target, field, text):
@ -1004,7 +1004,7 @@ class P10Protocol(IRCS2SProtocol):
return return
channel = args[0] channel = args[0]
chandata = self.channels[channel].deepcopy() chandata = self._channels[channel].deepcopy()
bans = [] bans = []
if args[-1].startswith('%'): if args[-1].startswith('%'):
@ -1068,11 +1068,11 @@ class P10Protocol(IRCS2SProtocol):
# Only save mode changes if the remote has lower TS than us. # Only save mode changes if the remote has lower TS than us.
changedmodes |= {('+%s' % mode, user) for mode in prefixes} changedmodes |= {('+%s' % mode, user) for mode in prefixes}
self.channels[channel].users.add(user) self._channels[channel].users.add(user)
# Statekeeping with timestamps # Statekeeping with timestamps
their_ts = int(args[1]) their_ts = int(args[1])
our_ts = self.channels[channel].ts our_ts = self._channels[channel].ts
self.updateTS(source, channel, their_ts, changedmodes) self.updateTS(source, channel, their_ts, changedmodes)
return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts, return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts,
@ -1096,7 +1096,7 @@ class P10Protocol(IRCS2SProtocol):
self.name, source, oldchans) self.name, source, oldchans)
for channel in oldchans: for channel in oldchans:
self.channels[channel].users.discard(source) self._channels[channel].users.discard(source)
self.users[source].channels.discard(channel) self.users[source].channels.discard(channel)
return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'} return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'}
@ -1106,10 +1106,10 @@ class P10Protocol(IRCS2SProtocol):
self.updateTS(source, channel, ts) self.updateTS(source, channel, ts)
self.users[source].channels.add(channel) self.users[source].channels.add(channel)
self.channels[channel].users.add(source) self._channels[channel].users.add(source)
return {'channel': channel, 'users': [source], 'modes': return {'channel': channel, 'users': [source], 'modes':
self.channels[channel].modes, 'ts': ts or int(time.time())} self._channels[channel].modes, 'ts': ts or int(time.time())}
handle_create = handle_join handle_create = handle_join
def handle_end_of_burst(self, source, command, args): def handle_end_of_burst(self, source, command, args):
@ -1140,9 +1140,9 @@ class P10Protocol(IRCS2SProtocol):
channel = args[0] channel = args[0]
topic = args[-1] topic = args[-1]
oldtopic = self.channels[channel].topic oldtopic = self._channels[channel].topic
self.channels[channel].topic = topic self._channels[channel].topic = topic
self.channels[channel].topicset = True self._channels[channel].topicset = True
return {'channel': channel, 'setter': args[1], 'text': topic, return {'channel': channel, 'setter': args[1], 'text': topic,
'oldtopic': oldtopic} 'oldtopic': oldtopic}
@ -1154,14 +1154,14 @@ class P10Protocol(IRCS2SProtocol):
modes = args[1] modes = args[1]
# Enumerate a list of our existing modes, including prefix modes. # Enumerate a list of our existing modes, including prefix modes.
existing = list(self.channels[channel].modes) existing = list(self._channels[channel].modes)
for pmode, userlist in self.channels[channel].prefixmodes.items(): for pmode, userlist in self._channels[channel].prefixmodes.items():
# Expand the prefix modes lists to individual ('o', 'UID') mode pairs. # Expand the prefix modes lists to individual ('o', 'UID') mode pairs.
modechar = self.cmodes.get(pmode) modechar = self.cmodes.get(pmode)
existing += [(modechar, user) for user in userlist] existing += [(modechar, user) for user in userlist]
# Back up the channel state. # Back up the channel state.
oldobj = self.channels[channel].deepcopy() oldobj = self._channels[channel].deepcopy()
changedmodes = [] changedmodes = []

View File

@ -76,8 +76,8 @@ class TS6Protocol(TS6BaseProtocol):
if not self.is_internal_client(client): if not self.is_internal_client(client):
log.error('(%s) Error trying to join %r to %r (no such client exists)', self.name, client, channel) log.error('(%s) Error trying to join %r to %r (no such client exists)', self.name, client, channel)
raise LookupError('No such PyLink client exists.') raise LookupError('No such PyLink client exists.')
self._send_with_prefix(client, "JOIN {ts} {channel} +".format(ts=self.channels[channel].ts, channel=channel)) self._send_with_prefix(client, "JOIN {ts} {channel} +".format(ts=self._channels[channel].ts, channel=channel))
self.channels[channel].users.add(client) self._channels[channel].users.add(client)
self.users[client].channels.add(channel) self.users[client].channels.add(channel)
def sjoin(self, server, channel, users, ts=None, modes=set()): def sjoin(self, server, channel, users, ts=None, modes=set()):
@ -106,8 +106,8 @@ class TS6Protocol(TS6BaseProtocol):
if not server: if not server:
raise LookupError('No such PyLink client exists.') raise LookupError('No such PyLink client exists.')
modes = set(modes or self.channels[channel].modes) modes = set(modes or self._channels[channel].modes)
orig_ts = self.channels[channel].ts orig_ts = self._channels[channel].ts
ts = ts or orig_ts ts = ts or orig_ts
# Get all the ban modes in a separate list. These are bursted using a separate BMASK # Get all the ban modes in a separate list. These are bursted using a separate BMASK
@ -119,7 +119,7 @@ class TS6Protocol(TS6BaseProtocol):
modechar = mode[0][-1] modechar = mode[0][-1]
if modechar in self.cmodes['*A']: if modechar in self.cmodes['*A']:
# Mode character is one of 'beIq' # Mode character is one of 'beIq'
if (modechar, mode[1]) in self.channels[channel].modes: if (modechar, mode[1]) in self._channels[channel].modes:
# Don't reset modes that are already set. # Don't reset modes that are already set.
continue continue
@ -153,7 +153,7 @@ class TS6Protocol(TS6BaseProtocol):
self._send_with_prefix(server, "SJOIN {ts} {channel} {modes} :{users}".format( self._send_with_prefix(server, "SJOIN {ts} {channel} {modes} :{users}".format(
ts=ts, users=namelist, channel=channel, ts=ts, users=namelist, channel=channel,
modes=self.join_modes(regularmodes))) modes=self.join_modes(regularmodes)))
self.channels[channel].users.update(uids) self._channels[channel].users.update(uids)
# Now, burst bans. # Now, burst bans.
# <- :42X BMASK 1424222769 #dev b :*!test@*.isp.net *!badident@* # <- :42X BMASK 1424222769 #dev b :*!test@*.isp.net *!badident@*
@ -183,7 +183,7 @@ class TS6Protocol(TS6BaseProtocol):
modes = list(modes) modes = list(modes)
if utils.isChannel(target): if utils.isChannel(target):
ts = ts or self.channels[target].ts ts = ts or self._channels[target].ts
# TMODE: # TMODE:
# parameters: channelTS, channel, cmode changes, opt. cmode parameters... # parameters: channelTS, channel, cmode changes, opt. cmode parameters...
@ -207,17 +207,17 @@ class TS6Protocol(TS6BaseProtocol):
# source: server # source: server
# propagation: broadcast # propagation: broadcast
# parameters: channel, topicTS, opt. topic setter, topic # parameters: channel, topicTS, opt. topic setter, topic
ts = self.channels[target].ts ts = self._channels[target].ts
servername = self.servers[numeric].name servername = self.servers[numeric].name
self._send_with_prefix(numeric, 'TB %s %s %s :%s' % (target, ts, servername, text)) self._send_with_prefix(numeric, 'TB %s %s %s :%s' % (target, ts, servername, text))
self.channels[target].topic = text self._channels[target].topic = text
self.channels[target].topicset = True self._channels[target].topicset = True
def invite(self, numeric, target, channel): def invite(self, numeric, target, channel):
"""Sends an INVITE from a PyLink client..""" """Sends an INVITE from a PyLink client.."""
if not self.is_internal_client(numeric): if not self.is_internal_client(numeric):
raise LookupError('No such PyLink client exists.') raise LookupError('No such PyLink client exists.')
self._send_with_prefix(numeric, 'INVITE %s %s %s' % (target, channel, self.channels[channel].ts)) self._send_with_prefix(numeric, 'INVITE %s %s %s' % (target, channel, self._channels[channel].ts))
def knock(self, numeric, target, text): def knock(self, numeric, target, text):
"""Sends a KNOCK from a PyLink client.""" """Sends a KNOCK from a PyLink client."""
@ -458,7 +458,7 @@ class TS6Protocol(TS6BaseProtocol):
# parameters: channelTS, channel, simple modes, opt. mode parameters..., nicklist # parameters: channelTS, channel, simple modes, opt. mode parameters..., nicklist
# <- :0UY SJOIN 1451041566 #channel +nt :@0UYAAAAAB # <- :0UY SJOIN 1451041566 #channel +nt :@0UYAAAAAB
channel = args[1] channel = args[1]
chandata = self.channels[channel].deepcopy() chandata = self._channels[channel].deepcopy()
userlist = args[-1].split() userlist = args[-1].split()
modestring = args[2:-1] or args[2] modestring = args[2:-1] or args[2]
@ -495,11 +495,11 @@ class TS6Protocol(TS6BaseProtocol):
# Only save mode changes if the remote has lower TS than us. # Only save mode changes if the remote has lower TS than us.
changedmodes |= {('+%s' % mode, user) for mode in finalprefix} changedmodes |= {('+%s' % mode, user) for mode in finalprefix}
self.channels[channel].users.add(user) self._channels[channel].users.add(user)
# Statekeeping with timestamps # Statekeeping with timestamps
their_ts = int(args[0]) their_ts = int(args[0])
our_ts = self.channels[channel].ts our_ts = self._channels[channel].ts
self.updateTS(servernumeric, channel, their_ts, changedmodes) self.updateTS(servernumeric, channel, their_ts, changedmodes)
return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts, return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts,
@ -516,7 +516,7 @@ class TS6Protocol(TS6BaseProtocol):
log.debug('(%s) Got /join 0 from %r, channel list is %r', log.debug('(%s) Got /join 0 from %r, channel list is %r',
self.name, numeric, oldchans) self.name, numeric, oldchans)
for channel in oldchans: for channel in oldchans:
self.channels[channel].users.discard(numeric) self._channels[channel].users.discard(numeric)
self.users[numeric].channels.discard(channel) self.users[numeric].channels.discard(channel)
return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'} return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'}
else: else:
@ -524,12 +524,12 @@ class TS6Protocol(TS6BaseProtocol):
self.updateTS(numeric, channel, ts) self.updateTS(numeric, channel, ts)
self.users[numeric].channels.add(channel) self.users[numeric].channels.add(channel)
self.channels[channel].users.add(numeric) self._channels[channel].users.add(numeric)
# We send users and modes here because SJOIN and JOIN both use one hook, # We send users and modes here because SJOIN and JOIN both use one hook,
# for simplicity's sake (with plugins). # for simplicity's sake (with plugins).
return {'channel': channel, 'users': [numeric], 'modes': return {'channel': channel, 'users': [numeric], 'modes':
self.channels[channel].modes, 'ts': ts} self._channels[channel].modes, 'ts': ts}
def handle_euid(self, numeric, command, args): def handle_euid(self, numeric, command, args):
"""Handles incoming EUID commands (user introduction).""" """Handles incoming EUID commands (user introduction)."""
@ -610,7 +610,7 @@ class TS6Protocol(TS6BaseProtocol):
# <- :42XAAAAAB TMODE 1437450768 #test -c+lkC 3 agte4 # <- :42XAAAAAB TMODE 1437450768 #test -c+lkC 3 agte4
# <- :0UYAAAAAD TMODE 0 #a +h 0UYAAAAAD # <- :0UYAAAAAD TMODE 0 #a +h 0UYAAAAAD
channel = args[1] channel = args[1]
oldobj = self.channels[channel].deepcopy() oldobj = self._channels[channel].deepcopy()
modes = args[2:] modes = args[2:]
changedmodes = self.parse_modes(channel, modes) changedmodes = self.parse_modes(channel, modes)
self.apply_modes(channel, changedmodes) self.apply_modes(channel, changedmodes)
@ -625,8 +625,8 @@ class TS6Protocol(TS6BaseProtocol):
ts = args[1] ts = args[1]
setter = args[2] setter = args[2]
topic = args[-1] topic = args[-1]
self.channels[channel].topic = topic self._channels[channel].topic = topic
self.channels[channel].topicset = True self._channels[channel].topicset = True
return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic} return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic}
def handle_etb(self, numeric, command, args): def handle_etb(self, numeric, command, args):
@ -637,8 +637,8 @@ class TS6Protocol(TS6BaseProtocol):
ts = args[2] ts = args[2]
setter = args[3] setter = args[3]
topic = args[-1] topic = args[-1]
self.channels[channel].topic = topic self._channels[channel].topic = topic
self.channels[channel].topicset = True self._channels[channel].topicset = True
return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic} return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic}
def handle_chghost(self, numeric, command, args): def handle_chghost(self, numeric, command, args):

View File

@ -106,7 +106,7 @@ class UnrealProtocol(TS6BaseProtocol):
if not self.is_internal_client(client): if not self.is_internal_client(client):
raise LookupError('No such PyLink client exists.') raise LookupError('No such PyLink client exists.')
self._send_with_prefix(client, "JOIN %s" % channel) self._send_with_prefix(client, "JOIN %s" % channel)
self.channels[channel].users.add(client) self._channels[channel].users.add(client)
self.users[client].channels.add(channel) self.users[client].channels.add(channel)
def sjoin(self, server, channel, users, ts=None, modes=set()): def sjoin(self, server, channel, users, ts=None, modes=set()):
@ -126,8 +126,8 @@ class UnrealProtocol(TS6BaseProtocol):
if not server: if not server:
raise LookupError('No such PyLink server exists.') raise LookupError('No such PyLink server exists.')
changedmodes = set(modes or self.channels[channel].modes) changedmodes = set(modes or self._channels[channel].modes)
orig_ts = self.channels[channel].ts orig_ts = self._channels[channel].ts
ts = ts or orig_ts ts = ts or orig_ts
uids = [] uids = []
itemlist = [] itemlist = []
@ -158,7 +158,7 @@ class UnrealProtocol(TS6BaseProtocol):
if modepair[0][-1] in self.cmodes['*A']: if modepair[0][-1] in self.cmodes['*A']:
# Bans, exempts, invex get expanded to forms like "&*!*@some.host" in SJOIN. # Bans, exempts, invex get expanded to forms like "&*!*@some.host" in SJOIN.
if (modepair[0][-1], modepair[1]) in self.channels[channel].modes: if (modepair[0][-1], modepair[1]) in self._channels[channel].modes:
# Mode is already set; skip it. # Mode is already set; skip it.
continue continue
@ -182,7 +182,7 @@ class UnrealProtocol(TS6BaseProtocol):
for line in utils.wrapArguments(sjoin_prefix, itemlist, self.S2S_BUFSIZE): for line in utils.wrapArguments(sjoin_prefix, itemlist, self.S2S_BUFSIZE):
self.send(line) self.send(line)
self.channels[channel].users.update(uids) self._channels[channel].users.update(uids)
self.updateTS(server, channel, ts, changedmodes) self.updateTS(server, channel, ts, changedmodes)
@ -217,7 +217,7 @@ class UnrealProtocol(TS6BaseProtocol):
modes[idx] = (mode[0], self._expandPUID(mode[1])) modes[idx] = (mode[0], self._expandPUID(mode[1]))
# The MODE command is used for channel mode changes only # The MODE command is used for channel mode changes only
ts = ts or self.channels[target].ts ts = ts or self._channels[target].ts
# 7 characters for "MODE", the space between MODE and the target, the space between the # 7 characters for "MODE", the space between MODE and the target, the space between the
# target and mode list, and the space between the mode list and TS. # target and mode list, and the space between the mode list and TS.
@ -532,15 +532,15 @@ class UnrealProtocol(TS6BaseProtocol):
log.debug('(%s) Got /join 0 from %r, channel list is %r', log.debug('(%s) Got /join 0 from %r, channel list is %r',
self.name, numeric, oldchans) self.name, numeric, oldchans)
for ch in oldchans: for ch in oldchans:
self.channels[ch].users.discard(numeric) self._channels[ch].users.discard(numeric)
self.users[numeric].channels.discard(ch) self.users[numeric].channels.discard(ch)
return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'} return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'}
else: else:
for channel in args[0].split(','): for channel in args[0].split(','):
c = self.channels[channel] c = self._channels[channel]
self.users[numeric].channels.add(channel) self.users[numeric].channels.add(channel)
self.channels[channel].users.add(numeric) self._channels[channel].users.add(numeric)
# Call hooks manually, because one JOIN command in UnrealIRCd can # Call hooks manually, because one JOIN command in UnrealIRCd can
# have multiple channels... # have multiple channels...
self.call_hooks([numeric, command, {'channel': channel, 'users': [numeric], 'modes': self.call_hooks([numeric, command, {'channel': channel, 'users': [numeric], 'modes':
@ -551,7 +551,7 @@ class UnrealProtocol(TS6BaseProtocol):
# <- :001 SJOIN 1444361345 #test :001AAAAAA @001AAAAAB +001AAAAAC # <- :001 SJOIN 1444361345 #test :001AAAAAA @001AAAAAB +001AAAAAC
# <- :001 SJOIN 1483250129 #services +nt :+001OR9V02 @*~001DH6901 &*!*@test "*!*@blah.blah '*!*@yes.no # <- :001 SJOIN 1483250129 #services +nt :+001OR9V02 @*~001DH6901 &*!*@test "*!*@blah.blah '*!*@yes.no
channel = args[1] channel = args[1]
chandata = self.channels[channel].deepcopy() chandata = self._channels[channel].deepcopy()
userlist = args[-1].split() userlist = args[-1].split()
namelist = [] namelist = []
@ -614,9 +614,9 @@ class UnrealProtocol(TS6BaseProtocol):
# 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.channels[channel].users.add(user) self._channels[channel].users.add(user)
our_ts = self.channels[channel].ts our_ts = self._channels[channel].ts
their_ts = int(args[0]) their_ts = int(args[0])
self.updateTS(numeric, channel, their_ts, changedmodes) self.updateTS(numeric, channel, their_ts, changedmodes)
@ -677,7 +677,7 @@ class UnrealProtocol(TS6BaseProtocol):
# Also, we need to get rid of that extra space following the +f argument. :| # Also, we need to get rid of that extra space following the +f argument. :|
if utils.isChannel(args[0]): if utils.isChannel(args[0]):
channel = args[0] channel = args[0]
oldobj = self.channels[channel].deepcopy() oldobj = self._channels[channel].deepcopy()
modes = [arg for arg in args[1:] if arg] # normalize whitespace modes = [arg for arg in args[1:] if arg] # normalize whitespace
parsedmodes = self.parse_modes(channel, modes) parsedmodes = self.parse_modes(channel, modes)
@ -688,7 +688,7 @@ class UnrealProtocol(TS6BaseProtocol):
# attempt to set modes by us was rejected for some reason (usually due to # attempt to set modes by us was rejected for some reason (usually due to
# timestamps). Drop the mode change to prevent mode floods. # timestamps). Drop the mode change to prevent mode floods.
log.debug("(%s) Received mode bounce %s in channel %s! Our TS: %s", log.debug("(%s) Received mode bounce %s in channel %s! Our TS: %s",
self.name, modes, channel, self.channels[channel].ts) self.name, modes, channel, self._channels[channel].ts)
return return
self.apply_modes(channel, parsedmodes) self.apply_modes(channel, parsedmodes)
@ -849,9 +849,9 @@ class UnrealProtocol(TS6BaseProtocol):
setter = args[1] setter = args[1]
ts = args[2] ts = args[2]
oldtopic = self.channels[channel].topic oldtopic = self._channels[channel].topic
self.channels[channel].topic = topic self._channels[channel].topic = topic
self.channels[channel].topicset = True self._channels[channel].topicset = True
return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic, return {'channel': channel, 'setter': setter, 'ts': ts, 'text': topic,
'oldtopic': oldtopic} 'oldtopic': oldtopic}