From 9719bb799e6c3af20a566ab360b797b893960423 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sat, 27 Feb 2021 18:07:23 +0100 Subject: [PATCH] irclib: Send the bot user mode when advertized by the server It is enabld by default in order to be a good netizen, but can be overridden by admins if needed. References: * * https://github.com/ircv3/ircv3-specifications/pull/439 --- src/irclib.py | 20 +++++++++++++++++++- test/test_irclib.py | 46 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/irclib.py b/src/irclib.py index 5b78b8d22..01a2c7b79 100644 --- a/src/irclib.py +++ b/src/irclib.py @@ -2039,17 +2039,35 @@ class Irc(IrcCommandDispatcher, log.Firewalled): self.afterConnect = True # Let's reset nicks in case we had to use a weird one. self.alternateNicks = conf.supybot.nick.alternates()[:] + + self._setUmodes() + + do377 = do422 = do376 + + def _setUmodes(self): + # Get the configured umodes umodes = conf.supybot.networks.get(self.network).umodes() if umodes == '': umodes = conf.supybot.protocols.irc.umodes() + + # Add the bot mode if the server advertizes one; + # and if the configured umode doesn't already have it + # explicitly set or unset + bot_mode = self.state.supported.get("BOT") + if bot_mode and len(bot_mode) == 1: + if bot_mode not in umodes: + umodes += "+" + bot_mode + + # Filter out umodes not supported by the server supported = self.state.supported.get('umodes') if supported: acceptedchars = supported.union('+-') umodes = ''.join([m for m in umodes if m in acceptedchars]) + + # Send the umodes if umodes: log.info('Sending user modes to %s: %s', self.network, umodes) self.sendMsg(ircmsgs.mode(self.nick, umodes)) - do377 = do422 = do376 def do43x(self, msg, problem): if not self.afterConnect: diff --git a/test/test_irclib.py b/test/test_irclib.py index 1d82e066a..3f822493d 100644 --- a/test/test_irclib.py +++ b/test/test_irclib.py @@ -869,6 +869,52 @@ class IrcTestCase(SupyTestCase): self.irc.feedMsg(ircmsgs.IrcMsg(command='372', args=['nick', 'some message'])) self.irc.feedMsg(ircmsgs.IrcMsg(command='376', args=['nick'])) + def testSetUmodes(self): + def assertSentModes(modes): + self.assertEqual( + self.irc.takeMsg(), + ircmsgs.IrcMsg(command='MODE', args=['test', modes]), + ) + + self.irc.reset() + while self.irc.takeMsg(): + pass + + self.irc.state.supported["BOT"] = "" # invalid + self.irc._setUmodes() + self.assertIsNone(self.irc.takeMsg()) + + self.irc.state.supported["BOT"] = "bB" # invalid too + self.irc._setUmodes() + self.assertIsNone(self.irc.takeMsg()) + + del self.irc.state.supported["BOT"] + self.irc._setUmodes() + self.assertIsNone(self.irc.takeMsg()) + + self.irc.state.supported["BOT"] = "B" + self.irc._setUmodes() + assertSentModes("+B") + + self.irc.state.supported["BOT"] = "b" + self.irc._setUmodes() + assertSentModes("+b") + + # merge with configured umodes + with conf.supybot.protocols.irc.umodes.context("+B"): + self.irc._setUmodes() + assertSentModes("+B+b") + + # no duplicate if char is the same + with conf.supybot.protocols.irc.umodes.context("+b"): + self.irc._setUmodes() + assertSentModes("+b") + + # no duplicate if explicitly disabled + with conf.supybot.protocols.irc.umodes.context("-b"): + self.irc._setUmodes() + assertSentModes("-b") + def testMsgChannel(self): self.irc.reset()