diff --git a/coreplugin.py b/coreplugin.py index 1260565..32610e8 100644 --- a/coreplugin.py +++ b/coreplugin.py @@ -127,7 +127,7 @@ def handle_mode(irc, source, command, args): # client, revert any forced deoper attempts. if irc.isInternalClient(target) and not irc.isInternalClient(source): if ('-o', None) in modes and (target == irc.pseudoclient.uid or not utils.isManipulatableClient(irc, target)): - irc.proto.modeServer(irc.sid, target, {('+o', None)}) + irc.proto.mode(irc.sid, target, {('+o', None)}) utils.add_hook(handle_mode, 'MODE') def handle_operup(irc, source, command, args): diff --git a/docs/technical/pmodule-spec.md b/docs/technical/pmodule-spec.md index 73c2900..a1b953f 100644 --- a/docs/technical/pmodule-spec.md +++ b/docs/technical/pmodule-spec.md @@ -60,9 +60,9 @@ internals](https://github.com/GLolol/PyLink/blob/0.4.0-dev/classes.py#L267-L272) - **`message`**`(self, source, target, text)` - Sends a PRIVMSG from a PyLink client. -- **`modeClient`**`(self, source, target, modes, ts=None)` - Sends modes from a PyLink client. `modes` takes a set of `([+/-]mode char, mode arg)` tuples. +- **`mode`**`(self, source, target, modes, ts=None)` - Sends modes from a PyLink client. `modes` takes a set of `([+/-]mode char, mode arg)` tuples. -- **`modeServer`**`(self, source, target, modes, ts=None)` - Sends modes from a PyLink server. +- **`mode`**`(self, source, target, modes, ts=None)` - Sends modes from a PyLink server. - **`nick`**`(self, source, newnick)` - Changes the nick of a PyLink client. diff --git a/plugins/opercmds.py b/plugins/opercmds.py index 2c7d80e..c982b4f 100644 --- a/plugins/opercmds.py +++ b/plugins/opercmds.py @@ -225,7 +225,7 @@ def mode(irc, source, args): irc.reply("Error: No valid modes were given.") return - irc.proto.modeClient(irc.pseudoclient.uid, target, parsedmodes) + irc.proto.mode(irc.pseudoclient.uid, target, parsedmodes) # Call the appropriate hooks for plugins like relay. irc.callHooks([irc.pseudoclient.uid, 'OPERCMDS_MODEOVERRIDE', diff --git a/plugins/relay.py b/plugins/relay.py index bea7875..7f52922 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -618,10 +618,10 @@ def relayModes(irc, remoteirc, sender, channel, modes=None): # Check if the sender is a user; remember servers are allowed to set modes too. u = getRemoteUser(irc, remoteirc, sender, spawnIfMissing=False) if u: - remoteirc.proto.modeClient(u, remotechan, supported_modes) + remoteirc.proto.mode(u, remotechan, supported_modes) else: rsid = getRemoteSid(remoteirc, irc) - remoteirc.proto.modeServer(rsid, remotechan, supported_modes) + remoteirc.proto.mode(rsid, remotechan, supported_modes) def relayWhoisHandler(irc, target): user = irc.users[target] @@ -904,7 +904,7 @@ def handle_mode(irc, numeric, command, args): reversed_modes = utils.reverseModes(irc, target, modes, oldobj=oldchan) log.debug('(%s) Reversing mode changes of %r with %r (CLAIM).', irc.name, modes, reversed_modes) - irc.proto.modeClient(irc.pseudoclient.uid, target, reversed_modes) + irc.proto.mode(irc.pseudoclient.uid, target, reversed_modes) break else: # Set hideoper on remote opers, to prevent inflating @@ -918,7 +918,7 @@ def handle_mode(irc, numeric, command, args): modes.append(('-%s' % hideoper_mode, None)) remoteuser = getRemoteUser(irc, remoteirc, target, spawnIfMissing=False) if remoteuser and modes: - remoteirc.proto.modeClient(remoteuser, remoteuser, modes) + remoteirc.proto.mode(remoteuser, remoteuser, modes) utils.add_hook(handle_mode, 'MODE') diff --git a/protocols/inspircd.py b/protocols/inspircd.py index 33f9c2a..88d65fb 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -154,10 +154,15 @@ class InspIRCdProtocol(TS6BaseProtocol): userobj.opertype = otype self._send(target, 'OPERTYPE %s' % otype.replace(" ", "_")) - def _sendModes(self, numeric, target, modes, ts=None): - """Internal function to send mode changes from a PyLink client/server.""" + def mode(self, numeric, target, modes, ts=None): + """Sends mode changes from a PyLink client/server.""" # -> :9PYAAAAAA FMODE #pylink 1433653951 +os 9PYAAAAAA # -> :9PYAAAAAA MODE 9PYAAAAAA -i+w + + if (not self.irc.isInternalClient(numeric)) and \ + (not self.irc.isInternalServer(numeric)): + raise LookupError('No such PyLink client/server exists.') + log.debug('(%s) inspircd._sendModes: received %r for mode list', self.irc.name, modes) if ('+o', None) in modes and not utils.isChannel(target): # https://github.com/inspircd/inspircd/blob/master/src/modules/m_spanningtree/opertype.cpp#L26-L28 @@ -171,24 +176,6 @@ class InspIRCdProtocol(TS6BaseProtocol): else: self._send(numeric, 'MODE %s %s' % (target, joinedmodes)) - def modeClient(self, numeric, target, modes, ts=None): - """ - Sends mode changes from a PyLink client. should be - a list of (mode, arg) tuples, i.e. the format of utils.parseModes() output. - """ - if not self.irc.isInternalClient(numeric): - raise LookupError('No such PyLink client exists.') - self._sendModes(numeric, target, modes, ts=ts) - - def modeServer(self, numeric, target, modes, ts=None): - """ - Sends mode changes from a PyLink server. should be - a list of (mode, arg) tuples, i.e. the format of utils.parseModes() output. - """ - if not self.irc.isInternalServer(numeric): - raise LookupError('No such PyLink server exists.') - self._sendModes(numeric, target, modes, ts=ts) - def kill(self, numeric, target, reason): """Sends a kill from a PyLink client/server.""" if (not self.irc.isInternalClient(numeric)) and \ diff --git a/protocols/ts6.py b/protocols/ts6.py index 1c13a4b..7034378 100644 --- a/protocols/ts6.py +++ b/protocols/ts6.py @@ -132,10 +132,16 @@ class TS6Protocol(TS6BaseProtocol): # Only save our prefix modes in the channel state if our TS is lower than or equal to theirs. utils.applyModes(self.irc, channel, changedmodes) - def _sendModes(self, numeric, target, modes, ts=None): - """Internal function to send mode changes from a PyLink client/server.""" + def mode(self, numeric, target, modes, ts=None): + """Sends mode changes from a PyLink client/server.""" + + if (not self.irc.isInternalClient(numeric)) and \ + (not self.irc.isInternalServer(numeric)): + raise LookupError('No such PyLink client/server exists.') + utils.applyModes(self.irc, target, modes) modes = list(modes) + if utils.isChannel(target): ts = ts or self.irc.channels[utils.toLower(self.irc, target)].ts # TMODE: @@ -144,6 +150,8 @@ class TS6Protocol(TS6BaseProtocol): # On output, at most ten cmode parameters should be sent; if there are more, # multiple TMODE messages should be sent. while modes[:9]: + # Seriously, though. If you send more than 10 mode parameters in + # a line, charybdis will silently REJECT the entire command! joinedmodes = utils.joinModes(modes = [m for m in modes[:9] if m[0] not in self.irc.cmodes['*A']]) modes = modes[9:] self._send(numeric, 'TMODE %s %s %s' % (ts, target, joinedmodes)) @@ -151,24 +159,6 @@ class TS6Protocol(TS6BaseProtocol): joinedmodes = utils.joinModes(modes) self._send(numeric, 'MODE %s %s' % (target, joinedmodes)) - def modeClient(self, numeric, target, modes, ts=None): - """ - Sends mode changes from a PyLink client. should be - a list of (mode, arg) tuples, i.e. the format of utils.parseModes() output. - """ - if not self.irc.isInternalClient(numeric): - raise LookupError('No such PyLink client exists.') - self._sendModes(numeric, target, modes, ts=ts) - - def modeServer(self, numeric, target, modes, ts=None): - """ - Sends mode changes from a PyLink server. should be - a list of (mode, arg) tuples, i.e. the format of utils.parseModes() output. - """ - if not self.irc.isInternalServer(numeric): - raise LookupError('No such PyLink server exists.') - self._sendModes(numeric, target, modes, ts=ts) - def kill(self, numeric, target, reason): """Sends a kill from a PyLink client/server.""" diff --git a/protocols/unreal.py b/protocols/unreal.py index 7b3af63..5dcd757 100644 --- a/protocols/unreal.py +++ b/protocols/unreal.py @@ -190,9 +190,17 @@ class UnrealProtocol(TS6BaseProtocol): self._send(numeric, 'KILL %s :%s!PyLink (%s)' % (target, self.irc.serverdata['hostname'], reason)) self.removeClient(target) - def _sendModes(self, numeric, target, modes, ts=None): - """Internal function to send mode changes from a PyLink client/server.""" + def mode(self, numeric, target, modes, ts=None): + """ + Sends mode changes from a PyLink client/server. The mode list should be + a list of (mode, arg) tuples, i.e. the format of utils.parseModes() output. + """ # <- :unreal.midnight.vpn MODE #endlessvoid +ntCo GL 1444361345 + + if (not self.irc.isInternalClient(numeric)) and \ + (not self.irc.isInternalServer(numeric)): + raise LookupError('No such PyLink client/server exists.') + utils.applyModes(self.irc, target, modes) joinedmodes = utils.joinModes(modes) if utils.isChannel(target): @@ -208,24 +216,6 @@ class UnrealProtocol(TS6BaseProtocol): raise ProtocolError('Cannot force mode change on external clients!') self._send(target, 'UMODE2 %s' % joinedmodes) - def modeClient(self, numeric, target, modes, ts=None): - """ - Sends mode changes from a PyLink client. The mode list should be - a list of (mode, arg) tuples, i.e. the format of utils.parseModes() output. - """ - if not self.irc.isInternalClient(numeric): - raise LookupError('No such PyLink client exists.') - self._sendModes(numeric, target, modes, ts=ts) - - def modeServer(self, numeric, target, modes, ts=None): - """ - Sends mode changes from a PyLink server. The mode list should be - a list of (mode, arg) tuples, i.e. the format of utils.parseModes() output. - """ - if not self.irc.isInternalServer(numeric): - raise LookupError('No such PyLink server exists.') - self._sendModes(numeric, target, modes, ts=ts) - def topicServer(self, numeric, target, text): """Sends a TOPIC change from a PyLink server.""" if not self.irc.isInternalServer(numeric): diff --git a/tests/tests_common.py b/tests/tests_common.py index 6956a2e..69b3917 100644 --- a/tests/tests_common.py +++ b/tests/tests_common.py @@ -43,12 +43,12 @@ class CommonProtoTestCase(PluginTestCase): def testModeClient(self): testuser = self.proto.spawnClient('testcakes') self.irc.takeMsgs() - self.proto.modeClient(self.u, testuser.uid, [('+i', None), ('+w', None)]) + self.proto.mode(self.u, testuser.uid, [('+i', None), ('+w', None)]) self.assertEqual({('i', None), ('w', None)}, testuser.modes) # Default channels start with +nt self.assertEqual({('n', None), ('t', None)}, self.irc.channels['#pylink'].modes) - self.proto.modeClient(self.u, '#pylink', [('+s', None), ('+l', '30')]) + self.proto.mode(self.u, '#pylink', [('+s', None), ('+l', '30')]) self.assertEqual({('s', None), ('l', '30'), ('n', None), ('t', None)}, self.irc.channels['#pylink'].modes) cmds = self.irc.takeCommands(self.irc.takeMsgs())