Add experimental support for +draft/reply client capability on outgoing messages.

This commit is contained in:
Valentin Lorentz 2020-05-07 21:17:55 +02:00
parent eb1e27e20b
commit 83a8afde16
3 changed files with 79 additions and 0 deletions

View File

@ -236,6 +236,14 @@ def _makeReply(irc, msg, s,
# Finally, we'll return the actual message.
ret = msgmaker(target, s)
ret.tag('inReplyTo', msg)
if 'msgid' in msg.server_tags \
and conf.supybot.protocols.irc.experimentalExtensions() \
and 'message-tags' in irc.state.capabilities_ack:
# In theory, msgid being in server_tags implies message-tags was
# negotiated, but the +reply spec requires it explicitly. Plus, there's
# no harm in doing this extra check, in case a plugin is replying
# across network (as it may happen with '@network command').
ret.server_tags['+draft/reply'] = msg.server_tags['msgid']
return ret
def error(*args, **kwargs):

View File

@ -1219,6 +1219,13 @@ registerGlobalValue(supybot.protocols.irc, 'strictRfc',
requires you to message a nick such as services@this.network.server
then you you should set this to False.""")))
registerGlobalValue(supybot.protocols.irc, 'experimentalExtensions',
registry.Boolean(False, _("""Determines whether the bot will enable
draft/experimental extensions of the IRC protocol. Setting this to True
may break your bot at any time without warning and/or break your
configuration irreversibly. So keep it False unless you know what you are
doing.""")))
registerGlobalValue(supybot.protocols.irc, 'certfile',
registry.String('', _("""Determines what certificate file (if any) the bot
will use connect with SSL sockets by default.""")))

View File

@ -534,6 +534,70 @@ class PrivmsgTestCase(ChannelPluginTestCase):
self.assertRegexp('help first firstcmd', 'First', 0) # no re.I flag.
self.assertRegexp('help firstrepeat firstcmd', 'FirstRepeat', 0)
def testClientTagReply(self):
self.irc.addCallback(self.First(self.irc))
# no CAP, no msgid, no experimentalExtensions -> no +reply
self.irc.feedMsg(ircmsgs.IrcMsg(
command='PRIVMSG', prefix=self.prefix,
args=('#foo', '%s: firstcmd' % self.nick)))
msg = self.irc.takeMsg()
self.assertEqual(msg, ircmsgs.IrcMsg(
command='PRIVMSG', args=('#foo', '%s: foo' % self.nick)))
# CAP and msgid, not no experimentalExtensions -> no +reply
self.irc.feedMsg(ircmsgs.IrcMsg(
command='PRIVMSG', prefix=self.prefix,
args=('#foo', '%s: firstcmd' % self.nick),
server_tags={'msgid': 'foobar'}))
msg = self.irc.takeMsg()
self.assertEqual(msg, ircmsgs.IrcMsg(
command='PRIVMSG', args=('#foo', '%s: foo' % self.nick)))
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
# no CAP, but msgid and experimentalExtensions -> no +reply
self.irc.feedMsg(ircmsgs.IrcMsg(
command='PRIVMSG', prefix=self.prefix,
args=('#foo', '%s: firstcmd' % self.nick),
server_tags={'msgid': 'foobar'}))
msg = self.irc.takeMsg()
self.assertEqual(msg, ircmsgs.IrcMsg(
command='PRIVMSG', args=('#foo', '%s: foo' % self.nick)))
# msgid and experimentalExtensions, but no CAP -> no +reply
# (note that in theory it's impossible to receive msgid without
# the CAP, but the +reply spec explicitly requires to check it)
self.irc.feedMsg(ircmsgs.IrcMsg(
command='PRIVMSG', prefix=self.prefix,
args=('#foo', '%s: firstcmd' % self.nick),
server_tags={'msgid': 'foobar'}))
msg = self.irc.takeMsg()
self.assertEqual(msg, ircmsgs.IrcMsg(
command='PRIVMSG', args=('#foo', '%s: foo' % self.nick)))
try:
self.irc.state.capabilities_ack.add('message-tags')
# no msgid, but CAP and experimentalExtensions -> no +reply
self.irc.feedMsg(ircmsgs.IrcMsg(
command='PRIVMSG', prefix=self.prefix,
args=('#foo', '%s: firstcmd' % self.nick)))
msg = self.irc.takeMsg()
self.assertEqual(msg, ircmsgs.IrcMsg(
command='PRIVMSG', args=('#foo', '%s: foo' % self.nick)))
# all of CAP, msgid, experimentalExtensions -> yes +reply
self.irc.feedMsg(ircmsgs.IrcMsg(
command='PRIVMSG', prefix=self.prefix,
args=('#foo', '%s: firstcmd' % self.nick),
server_tags={'msgid': 'foobar'}))
msg = self.irc.takeMsg()
self.assertEqual(msg, ircmsgs.IrcMsg(
command='PRIVMSG', args=('#foo', '%s: foo' % self.nick),
server_tags={'+draft/reply': 'foobar'}))
finally:
self.irc.state.capabilities_ack.remove('message-tags')
class TwoRepliesFirstAction(callbacks.Plugin):
def testactionreply(self, irc, msg, args):
irc.reply('foo', action=True)