From a040c3c7d2be5bc373fd558734abff658c8814ef Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 23 Sep 2016 23:39:12 -0700 Subject: [PATCH] ServiceBot: modularize join() for explicit channel joining (#326) --- coremods/service_support.py | 17 +---------------- plugins/relay.py | 4 +--- utils.py | 38 +++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/coremods/service_support.py b/coremods/service_support.py index 5ef98f3..b239ed5 100644 --- a/coremods/service_support.py +++ b/coremods/service_support.py @@ -26,10 +26,6 @@ def spawn_service(irc, source, command, args): nick = irc.serverdata.get("%s_nick" % name) or conf.conf.get(name, {}).get('nick') or sbot.nick or name ident = irc.serverdata.get("%s_ident" % name) or conf.conf.get(name, {}).get('ident') or sbot.ident or name - # Specify modes to join the services bot with. - joinmodes = irc.serverdata.get("%s_joinmodes" % name) or conf.conf.get(name, {}).get('joinmodes') or '' - joinmodes = ''.join([m for m in joinmodes if m in irc.prefixmodes]) - if name != 'pylink' and irc.protoname == 'clientbot': # Prefix service bots spawned on Clientbot to prevent possible nick collisions. nick = 'PyLinkService@' + nick @@ -66,18 +62,7 @@ def spawn_service(irc, source, command, args): # TODO: channels should be tracked in a central database, not hardcoded # in conf. channels = set(irc.serverdata.get('channels', [])) | sbot.extra_channels.get(irc.name, set()) - - for chan in channels: - if utils.isChannel(chan): - log.debug('(%s) Joining services %s to channel %s with modes %r', irc.name, name, chan, joinmodes) - if joinmodes: # Modes on join were specified; use SJOIN to burst our service - irc.proto.sjoin(irc.sid, chan, [(joinmodes, u)]) - else: - irc.proto.join(u, chan) - - irc.callHooks([irc.sid, 'PYLINK_SERVICE_JOIN', {'channel': chan, 'users': [u]}]) - else: - log.warning('(%s) Ignoring invalid autojoin channel %r.', irc.name, chan) + sbot.join(irc, channels) utils.add_hook(spawn_service, 'PYLINK_NEW_SERVICE') diff --git a/plugins/relay.py b/plugins/relay.py index 5483730..5e37bee 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -511,9 +511,7 @@ def initializeChannel(irc, channel): log.debug('(%s) relay.initializeChannel: joining our (%s) users: %s', irc.name, remotenet, irc.channels[channel].users) relayJoins(irc, channel, irc.channels[channel].users, irc.channels[channel].ts) - world.services['pylink'].extra_channels[irc.name].add(channel) - if irc.pseudoclient and irc.pseudoclient.uid not in irc.channels[channel].users: - irc.proto.join(irc.pseudoclient.uid, channel) + world.services['pylink'].join(irc, channel) def removeChannel(irc, channel): """Destroys a relay channel by parting all of its users.""" diff --git a/utils.py b/utils.py index 55b23d2..8e106cc 100644 --- a/utils.py +++ b/utils.py @@ -235,6 +235,44 @@ class ServiceBot(): else: raise NotImplementedError("Network specific plugins not supported yet.") + def join(self, irc, channels, autojoin=True): + """ + Joins the given service bot to the given channel(s). + """ + try: + u = self.uids[irc.name] + except KeyError: + log.debug('(%s/%s) Skipping join(), UID not initialized yet', irc.name, self.name) + return + + # Ensure type safety: pluralize strings if only one channel was given, then convert to set. + if type(channels) == str: + channels = [channels] + channels = set(channels) + + # Specify modes to join the services bot with. + joinmodes = irc.serverdata.get("%s_joinmodes" % self.name) or conf.conf.get(self.name, {}).get('joinmodes') or '' + joinmodes = ''.join([m for m in joinmodes if m in irc.prefixmodes]) + + if autojoin: + log.debug('(%s/%s) Adding channels %s to autojoin', irc.name, self.name, channels) + self.extra_channels[irc.name] |= channels + + for chan in channels: + if isChannel(chan): + if u in irc.channels[chan].users: + log.debug('(%s) Skipping join of services %s to channel %s - it is already present', irc.name, self.name, chan) + continue + log.debug('(%s) Joining services %s to channel %s with modes %r', irc.name, self.name, chan, joinmodes) + if joinmodes: # Modes on join were specified; use SJOIN to burst our service + irc.proto.sjoin(irc.sid, chan, [(joinmodes, u)]) + else: + irc.proto.join(u, chan) + + irc.callHooks([irc.sid, 'PYLINK_SERVICE_JOIN', {'channel': chan, 'users': [u]}]) + else: + log.warning('(%s) Ignoring invalid autojoin channel %r.', irc.name, chan) + def reply(self, irc, text, notice=False, private=False): """Replies to a message as the service in question.""" servuid = self.uids.get(irc.name)