From 7d840ab2d570e5eb06e373d3f2fc5c161db6fb2e Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sat, 24 Aug 2024 10:18:54 +0200 Subject: [PATCH] Add config value supybot.reply.mores.instant.whenPrivate This allows overriding supybot.reply.mores.instant for private messages, where it is usually more tolerable to send multiple lines. However, this still defaults to 1, in order to not be abusable by default. --- src/callbacks.py | 15 ++++++++--- src/conf.py | 7 ++++++ test/test_callbacks.py | 56 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/callbacks.py b/src/callbacks.py index e9428c872..e3772c81b 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -769,6 +769,9 @@ class ReplyIrcProxy(RichReplyMethods): else: sendMsg = self.replyIrc.queueMsg + public = bool(self.msg.channel) + private = kwargs.get('private', False) or not public + if isinstance(self.replyIrc, self.__class__): s = s[:conf.supybot.reply.maximumLength()] return self.replyIrc.reply(s, @@ -813,8 +816,14 @@ class ReplyIrcProxy(RichReplyMethods): # (which is used like a stack) chunks.reverse() - instant = conf.get(conf.supybot.reply.mores.instant, - channel=target, network=self.replyIrc.network) + instant = 0 + if private: + # if zero, falls back to supybot.reply.mores.instant + instant = conf.get(conf.supybot.reply.mores.instant.whenPrivate, + network=self.replyIrc.network) + if instant <= 0: + instant = conf.get(conf.supybot.reply.mores.instant, + channel=target, network=self.replyIrc.network) # Big complex loop ahead, with lots of cases and opportunities for # off-by-one errors. Here is the meaning of each of the variables @@ -912,8 +921,6 @@ class ReplyIrcProxy(RichReplyMethods): if '!' in prefix and '@' in prefix: mask = prefix.split('!', 1)[1] self._mores[mask] = msgs - public = bool(self.msg.channel) - private = kwargs.get('private', False) or not public self._mores[msg.nick] = (private, msgs) return response diff --git a/src/conf.py b/src/conf.py index f090816b3..d0d202d14 100644 --- a/src/conf.py +++ b/src/conf.py @@ -547,6 +547,13 @@ registerChannelValue(supybot.reply.mores, 'instant', they are formed). Defaults to 1, which means that a more command will be required for all but the first chunk."""))) +# XXX: User value. +registerNetworkValue(supybot.reply.mores.instant, 'whenPrivate', + registry.NonNegativeInteger(0, _("""Determines how many mores will be sent + instantly (i.e., without the use of the more command, immediately when + they are formed) when sending messages in private. Defaults to 0, which means + that it defaults to the generic supybot.reply.mores.instant value."""))) + registerChannelValue(supybot.reply, 'oneToOne', registry.Boolean(True, _("""Determines whether the bot will send multi-message replies in a single message. This defaults to True diff --git a/test/test_callbacks.py b/test/test_callbacks.py index 6ce9c1569..7ac6c78bf 100644 --- a/test/test_callbacks.py +++ b/test/test_callbacks.py @@ -547,6 +547,13 @@ class PrivmsgTestCase(ChannelPluginTestCase): "'" + "foo " * 110 + " \x02(2 more messages)\x02") self.assertNoResponse(" ", timeout=0.1) + # not in private -> no effect + with conf.supybot.reply.mores.instant.inPrivate.context(2): + self.assertResponse( + "eval 'foo '*300", + "'" + "foo " * 110 + " \x02(2 more messages)\x02") + self.assertNoResponse(" ", timeout=0.1) + with conf.supybot.reply.mores.instant.context(2): self.assertResponse( "eval 'foo '*300", @@ -568,6 +575,55 @@ class PrivmsgTestCase(ChannelPluginTestCase): " " + "foo " * 79 + "'") self.assertNoResponse(" ", timeout=0.1) + def testReplyInstantInPrivate(self): + self.assertNoResponse(' ') + self.assertResponse( + "eval irc.reply('foo '*300, private=True)", + "foo " * 113 + "\x02(2 more messages)\x02") + self.assertResponse(" ", "None") + + with conf.supybot.reply.mores.instant.whenPrivate.context(2): + self.assertResponse( + "eval irc.reply('foo '*300, private=True)", + "foo " * 112 + "foo") + self.assertResponse( + " ", + " foo" * 112 + " \x02(1 more message)\x02") + self.assertResponse(" ", "None") + + with conf.supybot.reply.mores.instant.whenPrivate.context(2): + with conf.supybot.reply.mores.instant.context(3): # ignored + self.assertResponse( + "eval irc.reply('foo '*300, private=True)", + "foo " * 112 + "foo") + self.assertResponse( + " ", + " foo" * 112 + " \x02(1 more message)\x02") + self.assertResponse(" ", "None") + + # fall back because supybot.reply.mores.instant.inPrivate is 0 + with conf.supybot.reply.mores.instant.context(2): + self.assertResponse( + "eval irc.reply('foo '*300, private=True)", + "foo " * 112 + "foo") + self.assertResponse( + " ", + " foo" * 112 + " \x02(1 more message)\x02") + self.assertResponse(" ", "None") + + # fall back because supybot.reply.mores.instant.inPrivate is 0 + with conf.supybot.reply.mores.instant.context(3): + self.assertResponse( + "eval irc.reply('foo '*300, private=True)", + "foo " * 112 + "foo") + self.assertResponse( + " ", + " foo" * 112 + " ") + self.assertResponse( + " ", + "foo " * 75) + self.assertResponse(" ", "None") + def testReplyPrivate(self): # Send from a very long nick, which should be taken into account when # computing the reply overhead.