From eca40a3d7c3a181277aef7700d2c34472c888716 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sat, 7 Oct 2017 21:49:17 -0700 Subject: [PATCH] coremods/handlers: implement cleanup code for visible-state-only servers Closes #536. Closes #517. --- coremods/handlers.py | 26 ++++++++++++++++++++++++++ protocols/clientbot.py | 13 ++----------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/coremods/handlers.py b/coremods/handlers.py index 8e77ef5..20108b7 100644 --- a/coremods/handlers.py +++ b/coremods/handlers.py @@ -163,3 +163,29 @@ def handle_time(irc, source, command, args): timestring = time.ctime() irc.numeric(irc.sid, 391, source, '%s :%s' % (irc.hostname(), timestring)) utils.add_hook(handle_time, 'TIME') + +def _state_cleanup_core(irc, source, channel): + """ + Handles PART and KICK on clientbot-like networks (where only the users and channels we see are available) + by deleting channels when we leave and users when they leave all shared channels. + """ + if irc.has_cap('visible-state-only'): + # Delete channels that we were removed from. + if irc.pseudoclient and source == irc.pseudoclient.uid: + log.debug('(%s) state_cleanup: removing channel %s since we have left', irc.name, channel) + del irc._channels[channel] + + # Delete users no longer sharing a channel with us. + if not irc.users[source].channels: + log.debug('(%s) state_cleanup: removing user %s/%s who no longer shares a channel with us', + irc.name, source, irc.users[source].nick) + irc._remove_client(source) + +def stats_cleanup_part(irc, source, command, args): + for channel in args['channels']: + _state_cleanup_core(irc, source, channel) +utils.add_hook(stats_cleanup_part, 'PART', priority=-100) + +def stats_cleanup_kick(irc, source, command, args): + _state_cleanup_core(irc, args['target'], args['channel']) +utils.add_hook(stats_cleanup_kick, 'KICK', priority=-100) diff --git a/protocols/clientbot.py b/protocols/clientbot.py index 0442f62..828647e 100644 --- a/protocols/clientbot.py +++ b/protocols/clientbot.py @@ -916,11 +916,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol): if (not self.is_internal_client(source)) and not self.is_internal_server(source): # Don't repeat hooks if we're the kicker. - self.call_hooks([source, 'KICK', {'channel': channel, 'target': target, 'text': reason}]) - - # Delete channels that we were kicked from, for better state keeping. - if self.pseudoclient and target == self.pseudoclient.uid: - del self._channels[channel] + return {'channel': channel, 'target': target, 'text': reason} def handle_mode(self, source, command, args): """Handles MODE changes.""" @@ -1019,12 +1015,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol): self._channels[channel].remove_user(source) self.users[source].channels -= set(channels) - self.call_hooks([source, 'PART', {'channels': channels, 'text': reason}]) - - # Clear channels that are empty, or that we're parting. - for channel in channels: - if (self.pseudoclient and source == self.pseudoclient.uid) or not self._channels[channel].users: - del self._channels[channel] + return {'channels': channels, 'text': reason} def handle_ping(self, source, command, args): """