From 741fed9acd319638372ed246c7da299e37ae2356 Mon Sep 17 00:00:00 2001 From: James Lu Date: Wed, 30 Dec 2015 15:54:09 -0800 Subject: [PATCH] protocols: allow changing remote users' hosts in updateClient Closes #142. --- protocols/inspircd.py | 51 ++++++++++++++++++++++++++++++++---------- protocols/ts6.py | 16 ++++++++----- protocols/unreal.py | 52 +++++++++++++++++++++++++++++++++---------- 3 files changed, 90 insertions(+), 29 deletions(-) diff --git a/protocols/inspircd.py b/protocols/inspircd.py index 53b172a..c2f8967 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -231,20 +231,47 @@ class InspIRCdProtocol(TS6BaseProtocol): raise LookupError('No such PyLink PseudoClient exists.') self._send(numeric, 'ENCAP * KNOCK %s :%s' % (target, text)) - def updateClient(self, numeric, field, text): - """Updates the ident, host, or realname of a PyLink client.""" + def updateClient(self, target, field, text): + """Updates the ident, host, or realname of any connected client.""" field = field.upper() - if field == 'IDENT': - self.irc.users[numeric].ident = text - self._send(numeric, 'FIDENT %s' % text) - elif field == 'HOST': - self.irc.users[numeric].host = text - self._send(numeric, 'FHOST %s' % text) - elif field in ('REALNAME', 'GECOS'): - self.irc.users[numeric].realname = text - self._send(numeric, 'FNAME :%s' % text) + + if field not in ('IDENT', 'HOST', 'REALNAME', 'GECOS'): + raise NotImplementedError("Changing field %r of a client is " + "unsupported by this protocol." % field) + + if utils.isInternalClient(self.irc, target): + # It is one of our clients, use FIDENT/HOST/NAME. + if field == 'IDENT': + self.irc.users[target].ident = text + self._send(target, 'FIDENT %s' % text) + elif field == 'HOST': + self.irc.users[target].host = text + self._send(target, 'FHOST %s' % text) + elif field in ('REALNAME', 'GECOS'): + self.irc.users[target].realname = text + self._send(target, 'FNAME :%s' % text) else: - raise NotImplementedError("Changing field %r of a client is unsupported by this protocol." % field) + # It is a client on another server, use CHGIDENT/HOST/NAME. + if field == 'IDENT': + self.irc.users[target].ident = text + self._send(self.irc.sid, 'CHGIDENT %s %s' % (target, text)) + + # Send hook payloads for other plugins to listen to. + self.irc.callHooks([self.irc.sid, 'CHGIDENT', + {'target': target, 'newident': text}]) + elif field == 'HOST': + self.irc.users[target].host = text + self._send(self.irc.sid, 'CHGHOST %s %s' % (target, text)) + + self.irc.callHooks([self.irc.sid, 'CHGHOST', + {'target': target, 'newhost': text}]) + + elif field in ('REALNAME', 'GECOS'): + self.irc.users[target].realname = text + self._send(self.irc.sid, 'CHGNAME %s :%s' % (target, text)) + + self.irc.callHooks([self.irc.sid, 'CHGNAME', + {'target': target, 'newgecos': text}]) def pingServer(self, source=None, target=None): """Sends a PING to a target server. Periodic PINGs are sent to our uplink diff --git a/protocols/ts6.py b/protocols/ts6.py index c3c2482..0152d2a 100644 --- a/protocols/ts6.py +++ b/protocols/ts6.py @@ -223,14 +223,20 @@ class TS6Protocol(TS6BaseProtocol): # No text value is supported here; drop it. self._send(numeric, 'KNOCK %s' % target) - def updateClient(self, numeric, field, text): - """Updates the hostname of a PyLink client.""" + def updateClient(self, target, field, text): + """Updates the hostname of any connected client.""" field = field.upper() if field == 'HOST': - self.irc.users[numeric].host = text - self._send(self.irc.sid, 'CHGHOST %s :%s' % (numeric, text)) + self.irc.users[target].host = text + self._send(self.irc.sid, 'CHGHOST %s :%s' % (target, text)) + if not utils.isInternalClient(self.irc, target): + # If the target isn't one of our clients, send hook payload + # for other plugins to listen to. + self.irc.callHooks([self.irc.sid, 'CHGHOST', + {'target': target, 'newhost': text}]) else: - raise NotImplementedError("Changing field %r of a client is unsupported by this protocol." % field) + raise NotImplementedError("Changing field %r of a client is " + "unsupported by this protocol." % field) def pingServer(self, source=None, target=None): """Sends a PING to a target server. Periodic PINGs are sent to our uplink diff --git a/protocols/unreal.py b/protocols/unreal.py index 35bd0f3..5d27c03 100644 --- a/protocols/unreal.py +++ b/protocols/unreal.py @@ -239,20 +239,48 @@ class UnrealProtocol(TS6BaseProtocol): self.irc.channels[target].topic = text self.irc.channels[target].topicset = True - def updateClient(self, numeric, field, text): - """Updates the ident, host, or realname of a PyLink client.""" + def updateClient(self, target, field, text): + """Updates the ident, host, or realname of any connected client.""" field = field.upper() - if field == 'IDENT': - self.irc.users[numeric].ident = text - self._send(numeric, 'SETIDENT %s' % text) - elif field == 'HOST': - self.irc.users[numeric].host = text - self._send(numeric, 'SETHOST %s' % text) - elif field in ('REALNAME', 'GECOS'): - self.irc.users[numeric].realname = text - self._send(numeric, 'SETNAME :%s' % text) + + if field not in ('IDENT', 'HOST', 'REALNAME', 'GECOS'): + raise NotImplementedError("Changing field %r of a client is " + "unsupported by this protocol." % field) + + if utils.isInternalClient(self.irc, target): + # It is one of our clients, use SETIDENT/HOST/NAME. + if field == 'IDENT': + self.irc.users[target].ident = text + self._send(target, 'SETIDENT %s' % text) + elif field == 'HOST': + self.irc.users[target].host = text + self._send(target, 'SETHOST %s' % text) + elif field in ('REALNAME', 'GECOS'): + self.irc.users[target].realname = text + self._send(target, 'SETNAME :%s' % text) else: - raise NotImplementedError("Changing field %r of a client is unsupported by this protocol." % field) + # It is a client on another server, use CHGIDENT/HOST/NAME. + if field == 'IDENT': + self.irc.users[target].ident = text + self._send(self.irc.sid, 'CHGIDENT %s %s' % (target, text)) + + # Send hook payloads for other plugins to listen to. + self.irc.callHooks([self.irc.sid, 'CHGIDENT', + {'target': target, 'newident': text}]) + + elif field == 'HOST': + self.irc.users[target].host = text + self._send(self.irc.sid, 'CHGHOST %s %s' % (target, text)) + + self.irc.callHooks([self.irc.sid, 'CHGHOST', + {'target': target, 'newhost': text}]) + + elif field in ('REALNAME', 'GECOS'): + self.irc.users[target].realname = text + self._send(self.irc.sid, 'CHGNAME %s :%s' % (target, text)) + + self.irc.callHooks([self.irc.sid, 'CHGNAME', + {'target': target, 'newgecos': text}]) def inviteClient(self, numeric, target, channel): """Sends an INVITE from a PyLink client.."""