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
This commit is contained in:
Valentin Lorentz 2021-02-27 18:07:23 +01:00
parent 78dc45e99e
commit 9719bb799e
2 changed files with 65 additions and 1 deletions

View File

@ -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:

View File

@ -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()