Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-limnoria for openSUSE:Factory
checked in at 2022-07-15 13:52:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-limnoria (Old)
and /work/SRC/openSUSE:Factory/.python-limnoria.new.1523 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-limnoria"
Fri Jul 15 13:52:26 2022 rev:26 rq:989193 version:2022.07.03
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-limnoria/python-limnoria.changes
2022-04-21 15:48:52.932330563 +0200
+++
/work/SRC/openSUSE:Factory/.python-limnoria.new.1523/python-limnoria.changes
2022-07-15 13:52:43.903568340 +0200
@@ -1,0 +2,7 @@
+Thu Jul 14 13:53:25 UTC 2022 - Atri Bhattacharya <[email protected]>
+
+- Update to version 2022-07-03:
+ * PluginDownloader: replace automatic 2to3 step with a simple
+ warning.
+
+-------------------------------------------------------------------
Old:
----
limnoria-2022.03.19.tar.gz
New:
----
limnoria-2022.07.03.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-limnoria.spec ++++++
--- /var/tmp/diff_new_pack.Uzum38/_old 2022-07-15 13:52:44.383568496 +0200
+++ /var/tmp/diff_new_pack.Uzum38/_new 2022-07-15 13:52:44.387568497 +0200
@@ -18,9 +18,9 @@
%define skip_python2 1
%define appname limnoria
-%define srcver 2022-03-19
+%define srcver 2022-07-03
Name: python-limnoria
-Version: 2022.03.19
+Version: 2022.07.03
Release: 0
Summary: A modified version of Supybot (an IRC bot and framework)
License: BSD-3-Clause
@@ -87,6 +87,7 @@
%python_clone -a %{buildroot}%{_mandir}/man1/supybot-plugin-doc.1
%python_clone -a %{buildroot}%{_mandir}/man1/supybot-test.1
%python_clone -a %{buildroot}%{_mandir}/man1/supybot-wizard.1
+%python_clone -a %{buildroot}%{_mandir}/man1/supybot-reset-password.1
%python_clone -a %{buildroot}%{_bindir}/supybot
%python_clone -a %{buildroot}%{_bindir}/supybot-adduser
%python_clone -a %{buildroot}%{_bindir}/supybot-botchk
@@ -107,7 +108,7 @@
%{python_install_alternative supybot supybot-adduser supybot-botchk
supybot-plugin-create supybot-plugin-doc supybot-reset-password supybot-test
supybot-wizard
supybot.1 supybot-adduser.1 supybot-botchk.1 supybot-plugin-create.1
- supybot-plugin-doc.1 supybot-test.1 supybot-wizard.1
+ supybot-plugin-doc.1 supybot-reset-password.1 supybot-test.1 supybot-wizard.1
}
%postun
@@ -131,6 +132,7 @@
%python_alternative %{_mandir}/man1/supybot-botchk.1
%python_alternative %{_mandir}/man1/supybot-plugin-create.1
%python_alternative %{_mandir}/man1/supybot-plugin-doc.1
+%python_alternative %{_mandir}/man1/supybot-reset-password.1
%python_alternative %{_mandir}/man1/supybot-test.1
%python_alternative %{_mandir}/man1/supybot-wizard.1
++++++ limnoria-2022.03.19.tar.gz -> limnoria-2022.07.03.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/man/supybot-reset-password.1
new/Limnoria-master-2022-07-03/man/supybot-reset-password.1
--- old/Limnoria-master-2022-03-19/man/supybot-reset-password.1 1970-01-01
01:00:00.000000000 +0100
+++ new/Limnoria-master-2022-07-03/man/supybot-reset-password.1 2022-06-23
22:31:17.000000000 +0200
@@ -0,0 +1,35 @@
+.\" Process this file with
+.\" groff -man -Tascii supybot-reset-password.1
+.\"
+.TH SUPYBOT-RESET-PASSWORD 1 "JUNE 2022"
+.SH NAME
+supybot-reset-password \- Changes a user's password in a Supybot users.conf
file
+.SH SYNOPSIS
+.B supybot-reset-password
+.RI [ options ] " users.conf
+.SH DESCRIPTION
+.B supybot-reset-password
+changes a user's password in a Supybot users.conf file
+.SH OPTIONS
+.TP
+.B \-\^\-version
+Show version of program.
+.TP
+.BR \-h ", " \-\^\-help
+Show summary of options.
+.TP
+.BR \-u " NAME" "\fR,\fP \-\^\-username=" NAME
+Specifies the username to use for the new user.
+.TP
+.BR \-p " PASSWORD" "\fR,\fP \-\^\-password=" PASSWORD
+Specifies the new password to use for the new user.
+.SH "SEE ALSO"
+.IR python (1),
+.IR supybot (1),
+.IR supybot-adduser (1)
+.SH AUTHOR
+This manual page was originally written by Valentin Lorentz
+<progval plus limnoria at progval dot net>. Permission is granted to copy,
+distribute and/or modify this document under the terms of the Supybot
+license, a BSD-style license.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/plugins/AutoMode/plugin.py
new/Limnoria-master-2022-07-03/plugins/AutoMode/plugin.py
--- old/Limnoria-master-2022-03-19/plugins/AutoMode/plugin.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/AutoMode/plugin.py 2022-06-23
22:31:17.000000000 +0200
@@ -144,7 +144,7 @@
break
try:
do('op')
- if 'h' in irc.state.supported['prefix']:
+ if 'h' in irc.state.supported.get('prefix', ''):
do('halfop')
except Continue:
return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/plugins/BadWords/config.py
new/Limnoria-master-2022-07-03/plugins/BadWords/config.py
--- old/Limnoria-master-2022-03-19/plugins/BadWords/config.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/BadWords/config.py 2022-06-23
22:31:17.000000000 +0200
@@ -113,6 +113,9 @@
filtering. If it's True, however, it will interact poorly with other
plugins that do coloring or bolding of text.""")))
+conf.registerChannelValue(BadWords, 'selfCensor',
+ registry.Boolean(True, _("""Determines whether the bot will filter its own
+ messages.""")))
conf.registerChannelValue(BadWords, 'kick',
registry.Boolean(False, _("""Determines whether the bot will kick people
with
a warning when they use bad words.""")))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/plugins/BadWords/messages.pot
new/Limnoria-master-2022-07-03/plugins/BadWords/messages.pot
--- old/Limnoria-master-2022-03-19/plugins/BadWords/messages.pot
2022-03-17 22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/BadWords/messages.pot
2022-06-23 22:31:17.000000000 +0200
@@ -81,18 +81,24 @@
#: config.py:117
msgid ""
+"Determines whether the bot will filter its own\n"
+" messages."
+msgstr ""
+
+#: config.py:120
+msgid ""
"Determines whether the bot will kick people with\n"
" a warning when they use bad words."
msgstr ""
-#: config.py:120
+#: config.py:123
msgid ""
"You have been kicked for using a word\n"
" prohibited in the presence of this bot. Please use more appropriate\n"
" language in the future."
msgstr ""
-#: config.py:122
+#: config.py:125
msgid ""
"Determines the kick message used by the\n"
" bot when kicking users for saying bad words."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/plugins/BadWords/plugin.py
new/Limnoria-master-2022-07-03/plugins/BadWords/plugin.py
--- old/Limnoria-master-2022-03-19/plugins/BadWords/plugin.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/BadWords/plugin.py 2022-06-23
22:31:17.000000000 +0200
@@ -104,9 +104,10 @@
self.lastModified = time.time()
def outFilter(self, irc, msg):
+ channel = msg.channel
if self.filtering and msg.command == 'PRIVMSG' \
- and (self.words() or self.phrases()):
- channel = msg.channel
+ and (self.words() or self.phrases()) \
+ and self.registryValue('selfCensor', channel, irc.network):
self.updateRegexp(channel, irc.network)
s = msg.args[1]
if self.registryValue('stripFormatting'):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/plugins/Geography/plugin.py
new/Limnoria-master-2022-07-03/plugins/Geography/plugin.py
--- old/Limnoria-master-2022-03-19/plugins/Geography/plugin.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/Geography/plugin.py 2022-06-23
22:31:17.000000000 +0200
@@ -110,6 +110,21 @@
_("Could not find the timezone of this location."), Raise=True
)
+ def _format_utc_offset(self, offset_seconds):
+ sign = "+" if offset_seconds >= 0 else "-"
+
+ # Make modulos work as expected
+ offset_seconds = abs(offset_seconds)
+
+ (offset_minutes, offset_seconds) = divmod(offset_seconds, 60)
+ (offset_hours, offset_minutes) = divmod(offset_minutes, 60)
+ offset = f"{offset_hours}:{offset_minutes:02}:{offset_seconds:02}"
+
+ # hide seconds and minutes if they are zero
+ offset = re.sub("(:00)+$", "", offset)
+
+ return f"UTC{sign}{offset}"
+
@wrap(["text"])
def timezone(self, irc, msg, args, query):
"""<location name to search>
@@ -134,33 +149,28 @@
if timezone is None:
continue
- offset = str(datetime.datetime.now(tz=timezone).utcoffset())
- if not offset.startswith("-"):
- offset = "+" + offset
-
- # hide seconds and minutes if they are zero
- offset = re.sub("(:00)+$", "", offset)
+ offset_seconds = int(
+ datetime.datetime.now(tz=timezone).utcoffset().total_seconds())
+ offset = self._format_utc_offset(offset_seconds)
# Extract a human-friendly name, depending on the type of
# the timezone object:
if hasattr(timezone, "key"):
# instance of zoneinfo.ZoneInfo
- irc.reply(format("%s (currently UTC%s)", timezone.key, offset))
+ irc.reply(format("%s (currently %s)", timezone.key, offset))
return
elif hasattr(timezone, "zone"):
# instance of pytz.timezone
- irc.reply(format("%s (currently UTC%s)", timezone.zone,
offset))
+ irc.reply(format("%s (currently %s)", timezone.zone, offset))
return
else:
# probably datetime.timezone built from a constant offset
try:
- offset = timezone.utcoffset(now).seconds
+ offset = int(timezone.utcoffset(now).total_seconds())
except NotImplementedError:
continue
- hours = int(offset / 3600)
- minutes = int(offset / 60 % 60)
- irc.reply("UTC+%0.2i:%0.2i" % (hours, minutes))
+ irc.reply(self._format_utc_offset(offset))
return
irc.error(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/plugins/Geography/test.py
new/Limnoria-master-2022-07-03/plugins/Geography/test.py
--- old/Limnoria-master-2022-03-19/plugins/Geography/test.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/Geography/test.py 2022-06-23
22:31:17.000000000 +0200
@@ -68,41 +68,85 @@
@mock
def testTimezonePytz(self):
tz = pytz.timezone("Europe/Paris")
-
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone Foo Bar", r"Europe/Paris \(currently UTC\+[12]\)"
)
+ tz = pytz.timezone("America/New_York")
+ with patch.object(wikidata, "timezone_from_uri", return_value=tz):
+ self.assertRegexp(
+ "timezone New York", r"America/New_York \(currently UTC-[45]\)"
+ )
+
+ tz = pytz.timezone("Canada/Newfoundland")
+ with patch.object(wikidata, "timezone_from_uri", return_value=tz):
+ self.assertRegexp(
+ "timezone Newfoundland",
+ r"Canada/Newfoundland \(currently UTC-[23]:30\)"
+ )
+
+ tz = pytz.timezone("Asia/Kolkata")
+ with patch.object(wikidata, "timezone_from_uri", return_value=tz):
+ self.assertRegexp(
+ "timezone Delhi", r"Asia/Kolkata \(currently UTC\+5:30\)"
+ )
+
@skipIf(not zoneinfo, "Python is older than 3.9")
@mock
def testTimezoneZoneinfo(self):
tz = zoneinfo.ZoneInfo("Europe/Paris")
-
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
self.assertRegexp(
"timezone Foo Bar", r"Europe/Paris \(currently UTC\+[12]\)"
)
+ tz = zoneinfo.ZoneInfo("America/New_York")
+ with patch.object(wikidata, "timezone_from_uri", return_value=tz):
+ self.assertRegexp(
+ "timezone New York", r"America/New_York \(currently UTC-[45]\)"
+ )
+
+ tz = zoneinfo.ZoneInfo("Canada/Newfoundland")
+ with patch.object(wikidata, "timezone_from_uri", return_value=tz):
+ self.assertRegexp(
+ "timezone Newfoundland",
+ r"Canada/Newfoundland \(currently UTC-[23]:30\)"
+ )
+
+ tz = zoneinfo.ZoneInfo("Asia/Kolkata")
+ with patch.object(wikidata, "timezone_from_uri", return_value=tz):
+ self.assertRegexp(
+ "timezone Delhi", r"Asia/Kolkata \(currently UTC\+5:30\)"
+ )
+
@skipIf(not zoneinfo, "Python is older than 3.9")
@mock
def testTimezoneAbsolute(self):
tz = datetime.timezone(datetime.timedelta(hours=4))
-
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
- self.assertResponse("timezone Foo Bar", "UTC+04:00")
+ self.assertResponse("timezone Foo Bar", "UTC+4")
tz = datetime.timezone(datetime.timedelta(hours=4, minutes=30))
+ with patch.object(wikidata, "timezone_from_uri", return_value=tz):
+ self.assertResponse("timezone Foo Bar", "UTC+4:30")
+ tz = datetime.timezone(datetime.timedelta(hours=-4, minutes=30))
with patch.object(wikidata, "timezone_from_uri", return_value=tz):
- self.assertResponse("timezone Foo Bar", "UTC+04:30")
+ self.assertResponse("timezone Foo Bar", "UTC-3:30")
@skipIf(not network, "Network test")
def testTimezoneIntegration(self):
self.assertRegexp(
"timezone Metz, France", r"Europe/Paris \(currently UTC\+[12]\)"
)
- self.assertResponse("timezone Saint-Denis, La R??union", "UTC+04:00")
+ self.assertResponse("timezone Saint-Denis, La R??union", "UTC+4")
+ self.assertRegexp(
+ "timezone Delhi", r"Asia/Kolkata \(currently UTC\+5:30\)"
+ )
+ self.assertRegexp(
+ "timezone Newfoundland", r"UTC-[23]:30"
+ )
class GeographyLocaltimeTestCase(PluginTestCase):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/plugins/PluginDownloader/plugin.py
new/Limnoria-master-2022-07-03/plugins/PluginDownloader/plugin.py
--- old/Limnoria-master-2022-03-19/plugins/PluginDownloader/plugin.py
2022-03-17 22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/PluginDownloader/plugin.py
2022-06-23 22:31:17.000000000 +0200
@@ -121,11 +121,11 @@
assert directory is not None, \
'No valid directory in supybot.directories.plugins.'
+ possibly_incompatible = False
try:
assert archive.getmember(prefix + dirname).isdir(), \
'This is not a valid plugin (it is a file, not a directory).'
- run_2to3 = minisix.PY3
for file in archive.getmembers():
if file.name.startswith(prefix + dirname):
extractedFile = archive.extractfile(file)
@@ -140,42 +140,18 @@
os.mkdir(newFileName)
else:
with open(newFileName, 'ab') as fd:
- reload_imported = False
for line in extractedFile.readlines():
- if minisix.PY3:
- if b'import reload' in line:
- reload_imported = True
- elif not reload_imported and \
- b'reload(' in line:
- fd.write(b'from importlib import
reload\n')
- reload_imported = True
+ if file.name.endswith('__init__.py') and \
+ line.startswith((b'import config',
b'import plugin')):
+ possibly_incompatible = True
fd.write(line)
- if newFileName.endswith('__init__.py'):
- with open(newFileName) as fd:
- lines = list(filter(lambda x:'import plugin' in x,
- fd.readlines()))
- if lines and lines[0].startswith('from . import'):
- # This should be already Python 3-compatible
- run_2to3 = False
finally:
archive.close()
del archive
- if run_2to3:
- try:
- import lib2to3
- except ImportError:
- return _('Plugin is probably not compatible with your '
- 'Python version (3.x) and could not be converted '
- 'because 2to3 is not installed.')
- import subprocess
- fixers = []
- subprocess.Popen(['2to3', '-wn', os.path.join(directory, plugin)])
\
- .wait()
- return _('Plugin was designed for Python 2, but an attempt to '
- 'convert it to Python 3 has been made. There is no '
- 'guarantee it will work, though.')
- else:
- return _('Plugin successfully installed.')
+ if possibly_incompatible:
+ return _('Plugin installed. However, it may be incompatible with '
+ 'Python 3 and require manual code changes to work
correctly.')
+ return _('Plugin successfully installed.')
def getInfo(self, plugin):
archive = self._download(plugin)
@@ -201,65 +177,11 @@
'progval',
'Supybot-plugins'
),
- 'quantumlemur': GithubRepository(
- 'quantumlemur',
- 'Supybot-plugins',
- ),
- 'stepnem': GithubRepository(
- 'stepnem',
- 'supybot-plugins',
- ),
- 'code4lib-snapshot':GithubRepository(
- 'code4lib',
- 'supybot-plugins',
- 'Supybot-plugins-20060723',
- ),
- 'code4lib-edsu': GithubRepository(
- 'code4lib',
- 'supybot-plugins',
- 'edsu-plugins',
- ),
- 'code4lib': GithubRepository(
- 'code4lib',
- 'supybot-plugins',
- 'plugins',
- ),
- 'nanotube-bitcoin': GithubRepository(
- 'nanotube',
- 'supybot-bitcoin-'
- 'marketmonitor',
- ),
- 'mtughan-weather': GithubRepository(
- 'mtughan',
- 'Supybot-Weather',
- ),
'SpiderDave': GithubRepository(
'SpiderDave',
'spidey-supybot-plugins',
'Plugins',
),
- 'doorbot': GithubRepository(
- 'hacklab',
- 'doorbot',
- ),
- 'boombot': GithubRepository(
- 'nod',
- 'boombot',
- 'plugins',
- ),
- 'mailed-notifier': GithubRepository(
- 'tbielawa',
- 'supybot-mailed-notifier',
- ),
- 'pingdom': GithubRepository(
- 'rynop',
- 'supyPingdom',
- 'plugins',
- ),
- 'scrum': GithubRepository(
- 'amscanne',
- 'supybot-scrum',
- ),
'Hoaas': GithubRepository(
'Hoaas',
'Supybot-plugins'
@@ -268,23 +190,11 @@
'nyuszika7h',
'limnoria-plugins'
),
- 'nyuszika7h-old': GithubRepository(
- 'nyuszika7h',
- 'Supybot-plugins'
- ),
- 'resistivecorpse': GithubRepository(
- 'resistivecorpse',
- 'supybot-plugins'
- ),
'frumious': GithubRepository(
'frumiousbandersnatch',
'sobrieti-plugins',
'plugins',
),
- 'jonimoose': GithubRepository(
- 'Jonimoose',
- 'Supybot-plugins',
- ),
'skgsergio': GithubRepository(
'skgsergio',
'Limnoria-plugins',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/plugins/PluginDownloader/test.py
new/Limnoria-master-2022-07-03/plugins/PluginDownloader/test.py
--- old/Limnoria-master-2022-03-19/plugins/PluginDownloader/test.py
2022-03-17 22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/PluginDownloader/test.py
2022-06-23 22:31:17.000000000 +0200
@@ -29,11 +29,9 @@
###
import os
-import sys
import shutil
from supybot.test import *
-import supybot.utils.minisix as minisix
pluginsPath = '%s/test-plugins' % os.getcwd()
@@ -62,7 +60,7 @@
def testRepolist(self):
self.assertRegexp('repolist', '(.*, )?progval(, .*)?')
- self.assertRegexp('repolist', '(.*, )?quantumlemur(, .*)?')
+ self.assertRegexp('repolist', '(.*, )?jlu5(, .*)?')
self.assertRegexp('repolist progval', '(.*, )?AttackProtector(, .*)?')
def testInstallprogval(self):
@@ -76,44 +74,19 @@
self.assertRegexp('plugindownloader install progval Darcs',
'Error:.*not available.*supybot.commands.allowShell')
- def testInstallQuantumlemur(self):
- self.assertError('plugindownloader install quantumlemur
AttackProtector')
- self.assertNotError('plugindownloader install quantumlemur Listener')
- self.assertError('plugindownloader install quantumlemur
AttackProtector')
- self._testPluginInstalled('Listener')
-
- def testInstallStepnem(self):
- self.assertNotError('plugindownloader install stepnem Freenode')
- self._testPluginInstalled('Freenode')
-
- def testInstallNanotubeBitcoin(self):
- self.assertNotError('plugindownloader install nanotube-bitcoin GPG')
- self._testPluginInstalled('GPG')
-
- def testInstallMtughanWeather(self):
- self.assertNotError('plugindownloader install mtughan-weather '
- 'WunderWeather')
- self._testPluginInstalled('WunderWeather')
-
- def testInstallSpiderDave(self):
- self.assertNotError('plugindownloader install SpiderDave Pastebin')
- self._testPluginInstalled('Pastebin')
-
def testInstallNonAsciiInit(self):
self.assertNotError('plugindownloader install Hoaas DuckDuckGo')
self._testPluginInstalled('DuckDuckGo')
+ def testInstallLegacyWarning(self):
+ self.assertRegexp('plugindownloader install frumious Codepoints',
+ 'may be incompatible')
+
def testInfo(self):
self.assertResponse('plugindownloader info progval Twitter',
'Advanced Twitter plugin for Supybot, with capabilities '
'handling, and per-channel user account.')
- if minisix.PY3:
- def test_2to3(self):
- self.assertRegexp('plugindownloader install SpiderDave Pastebin',
- 'convert')
- self.assertNotError('load Pastebin')
-
if not network:
class PluginDownloaderTestCase(PluginTestCase):
pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/plugins/Time/plugin.py
new/Limnoria-master-2022-07-03/plugins/Time/plugin.py
--- old/Limnoria-master-2022-03-19/plugins/Time/plugin.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/Time/plugin.py 2022-06-23
22:31:17.000000000 +0200
@@ -28,10 +28,11 @@
# POSSIBILITY OF SUCH DAMAGE.
###
+import re
import sys
import time
TIME = time # For later use.
-from datetime import datetime
+from datetime import datetime, timedelta, timezone
import supybot.conf as conf
import supybot.log as log
@@ -194,25 +195,35 @@
elapsed = wrap(elapsed, ['int'])
@internationalizeDocstring
- def tztime(self, irc, msg, args, timezone):
+ def tztime(self, irc, msg, args, tz):
"""<region>/<city> (or <region>/<state>/<city>)
Takes a city and its region, and returns its local time. This
command uses the IANA Time Zone Database."""
- try:
- timezone = utils.time.iana_timezone(timezone)
- except utils.time.UnknownTimeZone:
- irc.error(_('Unknown timezone'))
- except utils.time.MissingTimezoneLibrary:
- irc.error(_(
- 'Timezone-related commands are not available. '
- 'Your administrator need to either upgrade Python to '
- 'version 3.9 or greater, or install pytz.'))
- except utils.time.TimezoneException as e:
- irc.error(e.args[0])
+ parsed_utc_tz = re.match(
+ "UTC(?P<hours>[-+][0-9]+)(:(?P<minutes>[0-6][0-9]))?", tz)
+ if parsed_utc_tz:
+ groups = parsed_utc_tz.groupdict()
+ tz = timezone(timedelta(
+ hours=int(groups["hours"]),
+ minutes=int(groups["minutes"] or "00")
+ ))
else:
- format = self.registryValue("format", msg.channel, irc.network)
- irc.reply(datetime.now(timezone).strftime(format))
+ try:
+ tz = utils.time.iana_timezone(tz)
+ except utils.time.UnknownTimeZone:
+ irc.error(_('Unknown timezone'), Raise=True)
+ except utils.time.MissingTimezoneLibrary:
+ irc.error(_(
+ 'Timezone-related commands are not available. '
+ 'Your administrator need to either upgrade Python to '
+ 'version 3.9 or greater, or install pytz.'),
+ Raise=True)
+ except utils.time.TimezoneException as e:
+ irc.error(e.args[0], Raise=True)
+
+ format = self.registryValue("format", msg.channel, irc.network)
+ irc.reply(datetime.now(tz).strftime(format))
tztime = wrap(tztime, ['text'])
def ddate(self, irc, msg, args, year=None, month=None, day=None):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/plugins/Time/test.py
new/Limnoria-master-2022-07-03/plugins/Time/test.py
--- old/Limnoria-master-2022-03-19/plugins/Time/test.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/Time/test.py 2022-06-23
22:31:17.000000000 +0200
@@ -97,6 +97,8 @@
self.assertNotError('tztime Europe/Paris')
self.assertNotError('tztime America/Indiana/Knox')
self.assertNotError('tztime UTC')
+ self.assertNotError('tztime UTC+10')
+ self.assertNotError('tztime UTC+5:30')
self.assertError('tztime Europe/Gniarf')
@skipIf(not has_dateutil, 'python-dateutil is missing')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/plugins/Web/plugin.py
new/Limnoria-master-2022-07-03/plugins/Web/plugin.py
--- old/Limnoria-master-2022-03-19/plugins/Web/plugin.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/plugins/Web/plugin.py 2022-06-23
22:31:17.000000000 +0200
@@ -151,7 +151,8 @@
size = conf.supybot.protocols.http.peekSize()
parsed_url = utils.web.urlparse(url)
- if parsed_url.netloc.endswith(('youtube.com', '.youtube.com')):
+ if parsed_url.netloc == 'youtube.com' \
+ or parsed_url.netloc.endswith(('.youtube.com')):
# there is a lot of Javascript before the <title>
size = 409600
if parsed_url.netloc in ('reddit.com', 'www.reddit.com',
'new.reddit.com'):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/scripts/supybot-plugin-create
new/Limnoria-master-2022-07-03/scripts/supybot-plugin-create
--- old/Limnoria-master-2022-03-19/scripts/supybot-plugin-create
2022-03-17 22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/scripts/supybot-plugin-create
2022-06-23 22:31:17.000000000 +0200
@@ -92,13 +92,10 @@
from supybot import utils, plugins, ircutils, callbacks
from supybot.commands import *
-try:
- from supybot.i18n import PluginInternationalization
- _ = PluginInternationalization('%s')
-except ImportError:
- # Placeholder that allows to run the plugin on a bot
- # without the i18n module
- _ = lambda x: x
+from supybot.i18n import PluginInternationalization
+
+
+_ = PluginInternationalization('%s')
class %s(callbacks.Plugin):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Limnoria-master-2022-03-19/scripts/supybot-reset-password
new/Limnoria-master-2022-07-03/scripts/supybot-reset-password
--- old/Limnoria-master-2022-03-19/scripts/supybot-reset-password
2022-03-17 22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/scripts/supybot-reset-password
2022-06-23 22:31:17.000000000 +0200
@@ -51,7 +51,7 @@
help='username for the user.')
parser.add_option('-p', '--password', action='store', default='',
dest='password',
- help='password for the user.')
+ help='new password for the user.')
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error('Specify the users.conf file you\'d like to use. '
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/setup.py
new/Limnoria-master-2022-07-03/setup.py
--- old/Limnoria-master-2022-03-19/setup.py 2022-03-17 22:29:10.000000000
+0100
+++ new/Limnoria-master-2022-07-03/setup.py 2022-06-23 22:31:17.000000000
+0200
@@ -216,6 +216,7 @@
('share/man/man1', ['man/supybot-botchk.1']),
('share/man/man1', ['man/supybot-wizard.1']),
('share/man/man1', ['man/supybot-adduser.1']),
+ ('share/man/man1', ['man/supybot-reset-password.1']),
('share/man/man1', ['man/supybot-plugin-doc.1']),
('share/man/man1', ['man/supybot-plugin-create.1']),
],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/__init__.py
new/Limnoria-master-2022-07-03/src/__init__.py
--- old/Limnoria-master-2022-03-19/src/__init__.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/src/__init__.py 2022-06-23
22:31:17.000000000 +0200
@@ -33,10 +33,7 @@
from . import i18n
-builtins = (__builtins__ if isinstance(__builtins__, dict) else
__builtins__.__dict__)
-builtins['supybotInternationalization'] = i18n.PluginInternationalization()
from . import utils
-del builtins['supybotInternationalization']
(__builtins__ if isinstance(__builtins__, dict) else
__builtins__.__dict__)['format'] = utils.str.format
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/callbacks.py
new/Limnoria-master-2022-07-03/src/callbacks.py
--- old/Limnoria-master-2022-03-19/src/callbacks.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/src/callbacks.py 2022-06-23
22:31:17.000000000 +0200
@@ -256,6 +256,10 @@
# 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']
+ if msg.channel and not irc.isChannel(ret.args[0]):
+ # If replying in non-channel to a channel message, use the tag
+ # defined in https://github.com/ircv3/ircv3-specifications/pull/498
+ ret.server_tags["+draft/channel-context"] = msg.channel
return ret
def error(*args, **kwargs):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/conf.py
new/Limnoria-master-2022-07-03/src/conf.py
--- old/Limnoria-master-2022-03-19/src/conf.py 2022-03-17 22:29:10.000000000
+0100
+++ new/Limnoria-master-2022-07-03/src/conf.py 2022-06-23 22:31:17.000000000
+0200
@@ -911,6 +911,10 @@
ValidDriverModule('default', _("""Determines what driver module the
bot will use. Current, the only (and default) driver is Socket.""")))
+registerGlobalValue(supybot.drivers, 'minReconnectWait',
+ registry.PositiveFloat(10.0, _("""Determines the minimum time the bot will
+ wait before attempting to reconnect to an IRC server.""")))
+
registerGlobalValue(supybot.drivers, 'maxReconnectWait',
registry.PositiveFloat(300.0, _("""Determines the maximum time the bot will
wait before attempting to reconnect to an IRC server. The bot may, of
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/drivers/Socket.py
new/Limnoria-master-2022-07-03/src/drivers/Socket.py
--- old/Limnoria-master-2022-03-19/src/drivers/Socket.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/src/drivers/Socket.py 2022-06-23
22:31:17.000000000 +0200
@@ -92,7 +92,7 @@
return ret
def resetDelay(self):
- self.currentDelay = 10.0
+ self.currentDelay = conf.supybot.drivers.minReconnectWait()
def _getNextServer(self):
oldServer = getattr(self, 'currentServer', None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/i18n.py
new/Limnoria-master-2022-07-03/src/i18n.py
--- old/Limnoria-master-2022-03-19/src/i18n.py 2022-03-17 22:29:10.000000000
+0100
+++ new/Limnoria-master-2022-07-03/src/i18n.py 2022-06-23 22:31:17.000000000
+0200
@@ -43,9 +43,11 @@
IN_MSGID = 2
WAITING_FOR_MSGSTR = 3
IN_MSGSTR = 4
+NEXT_IS_FUZZY = 5
MSGID = 'msgid "'
MSGSTR = 'msgstr "'
+FUZZY = '#, fuzzy'
currentLocale = 'en'
@@ -68,10 +70,12 @@
"""Imports the conf into this module"""
global conf
conf = __import__('supybot.conf').conf
+ class Languages(conf.registry.OnlySomeStrings):
+ validStrings = ['de', 'en', 'es', 'fi', 'fr', 'it']
conf.registerGlobalValue(conf.supybot, 'language',
- conf.registry.String(currentLocale, """Determines the bot's default
- language if translations exist. Currently supported are 'de', 'en',
- 'es', 'fi', 'fr' and 'it'."""))
+ Languages(currentLocale, """Determines the bot's default
+ language if translations exist. Currently supported are: %s"""
+ % ', '.join(Languages.validStrings)))
conf.supybot.language.addCallback(reloadLocalesIfRequired)
def getPluginDir(plugin_name):
@@ -111,7 +115,6 @@
i18nClasses = weakref.WeakValueDictionary()
internationalizedCommands = weakref.WeakValueDictionary()
-internationalizedFunctions = [] # No need to know their name
def reloadLocalesIfRequired():
global currentLocale
@@ -122,12 +125,13 @@
reloadLocales()
def reloadLocales():
+ import supybot.utils as utils
+
for pluginClass in i18nClasses.values():
pluginClass.loadLocale()
for command in list(internationalizedCommands.values()):
internationalizeDocstring(command)
- for function in internationalizedFunctions:
- function.loadLocale()
+ utils.str._relocalizeFunctions(PluginInternationalization())
def normalize(string, removeNewline=False):
import supybot.utils as utils
@@ -148,7 +152,13 @@
line = line[0:-1] # Remove the ending \n
line = line
- if line.startswith(MSGID):
+ if step == WAITING_FOR_MSGID and line.startswith(FUZZY):
+ step = NEXT_IS_FUZZY
+ elif step == NEXT_IS_FUZZY and line.startswith(MSGID):
+ # Don't use fuzzy strings; they may have a mismatched number of %s
or be
+ # outright wrong; use English instead.
+ step = WAITING_FOR_MSGID
+ elif line.startswith(MSGID):
# Don't check if step is WAITING_FOR_MSGID
untranslated = ''
translated = ''
@@ -193,7 +203,6 @@
return translations
-i18nSupybot = None
def PluginInternationalization(name='supybot'):
# This is a proxy that prevents having several objects for the same plugin
if name in i18nClasses:
@@ -318,40 +327,6 @@
name in self._l10nFunctions:
return self._l10nFunctions[name]
- def internationalizeFunction(self, name):
- """Decorates functions and internationalize their code.
-
- Only useful for Supybot core functions"""
- if self.name != 'supybot':
- return
- class FunctionInternationalizer:
- def __init__(self, parent, name):
- self._parent = parent
- self._name = name
- def __call__(self, obj):
- obj = InternationalizedFunction(self._parent, self._name, obj)
- obj.loadLocale()
- return obj
- return FunctionInternationalizer(self, name)
-
-class InternationalizedFunction:
- """Proxy for functions that need to be fully localized.
-
- The localization code is in locales/LOCALE.py"""
- def __init__(self, internationalizer, name, function):
- self._internationalizer = internationalizer
- self._name = name
- self._origin = function
- internationalizedFunctions.append(self)
- def loadLocale(self):
- self.__call__ = self._internationalizer.localizeFunction(self._name)
- if self.__call__ == None:
- self.restore()
- def restore(self):
- self.__call__ = self._origin
-
- def __call__(self, *args, **kwargs):
- return self._origin(*args, **kwargs)
try:
class InternationalizedString(str):
@@ -367,6 +342,7 @@
know if a string is already localized"""
pass
+
def internationalizeDocstring(obj):
"""Decorates functions and internationalize their docstring.
@@ -383,3 +359,13 @@
# attribute '__doc__' of 'type' objects is not writable
pass
return obj
+
+
+def _install():
+ from . import utils
+ _ = PluginInternationalization()
+ utils.gen._ = _
+ utils.str._ = _
+ utils.str._relocalizeFunctions(_)
+
+_install()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/irclib.py
new/Limnoria-master-2022-07-03/src/irclib.py
--- old/Limnoria-master-2022-03-19/src/irclib.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/src/irclib.py 2022-06-23
22:31:17.000000000 +0200
@@ -1809,9 +1809,13 @@
`msg` is the message that triggered this call."""
self.state.fsm.expect_state([
- # Normal CAP ACK / CAP NAK during cap negotiation
+ # Normal CAP ACK / CAP NAK during cap negotiation:
IrcStateFsm.States.INIT_CAP_NEGOTIATION,
- # CAP ACK / CAP NAK after a CAP NEW (probably)
+ # Sigyn sends CAP REQ when it sees RPL_SASLSUCCESS, so we get the
+ # CAP ACK while waiting for MOTD on some IRCds (eg. InspIRCd):
+ IrcStateFsm.States.INIT_WAITING_MOTD,
+ IrcStateFsm.States.INIT_MOTD,
+ # CAP ACK / CAP NAK after a CAP NEW (probably):
IrcStateFsm.States.CONNECTED,
])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/setup.py
new/Limnoria-master-2022-07-03/src/setup.py
--- old/Limnoria-master-2022-03-19/src/setup.py 2022-03-17 22:29:10.000000000
+0100
+++ new/Limnoria-master-2022-07-03/src/setup.py 2022-06-23 22:31:17.000000000
+0200
@@ -79,7 +79,14 @@
break
module_name = kwargs['name'].replace('-', '_')
- kwargs.setdefault('packages', [module_name])
+
+ if 'packages' not in kwargs:
+ kwargs["packages"] = [module_name] + [
+ "%s.%s" % (module_name, package_name.replace('-', '_'))
+ for package_name
+ in setuptools.find_packages(where=".")
+ ]
+
kwargs.setdefault('package_dir', {module_name: '.'})
kwargs.setdefault('entry_points', {
'limnoria.plugins': '%s = %s' % (capitalized_name, module_name)})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/utils/__init__.py
new/Limnoria-master-2022-07-03/src/utils/__init__.py
--- old/Limnoria-master-2022-03-19/src/utils/__init__.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/src/utils/__init__.py 2022-06-23
22:31:17.000000000 +0200
@@ -50,6 +50,7 @@
builtins = (__builtins__ if isinstance(__builtins__, dict) else
__builtins__.__dict__)
+
# We use this often enough that we're going to stick it in builtins.
def force(x):
if callable(x):
@@ -58,8 +59,6 @@
return x
builtins['force'] = force
-internationalization = builtins.get('supybotInternationalization', None)
-
# These imports need to happen below the block above, so things get put into
# __builtins__ appropriately.
from .gen import *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/utils/gen.py
new/Limnoria-master-2022-07-03/src/utils/gen.py
--- old/Limnoria-master-2022-03-19/src/utils/gen.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/src/utils/gen.py 2022-06-23
22:31:17.000000000 +0200
@@ -45,7 +45,9 @@
from .str import format
from .file import mktemp
from . import minisix
-from . import internationalization as _
+
+# will be replaced by supybot.i18n.install()
+_ = lambda x: x
def warn_non_constant_time(f):
@functools.wraps(f)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/src/utils/str.py
new/Limnoria-master-2022-07-03/src/utils/str.py
--- old/Limnoria-master-2022-03-19/src/utils/str.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/src/utils/str.py 2022-06-23
22:31:17.000000000 +0200
@@ -38,20 +38,46 @@
import time
import string
import textwrap
+import functools
from . import minisix
from .iter import any
from .structures import TwoWayDictionary
-from . import internationalization as _
-internationalizeFunction = _.internationalizeFunction
-
try:
from charade.universaldetector import UniversalDetector
charadeLoaded = True
except ImportError:
charadeLoaded = False
+# will be replaced by supybot.i18n.install()
+_ = lambda x: x
+
+# used by supybot.i18n.reloadLocales() to (re)load the localized function of
+# these functions
+_localizedFunctions = {}
+_defaultFunctions = {}
+
+
+def internationalizeFunction(f):
+ f_name = f.__name__
+ _localizedFunctions[f_name] = f
+ _defaultFunctions[f_name] = f
+
+ @functools.wraps(f)
+ def newf(*args, **kwargs):
+ f = _localizedFunctions[f_name]
+ assert f is not None, "_localizedFunctions[%s] is None" % f_name
+ return f(*args, **kwargs)
+
+ return newf
+
+
+def _relocalizeFunctions(localizer):
+ for f_name in list(_localizedFunctions):
+ f = localizer.localizeFunction(f_name) or _defaultFunctions[f_name]
+ _localizedFunctions[f_name] = f
+
if minisix.PY3:
def decode_raw_line(line):
#first, try to decode using utf-8
@@ -390,7 +416,7 @@
L[i] = L[i].upper()
return ''.join(L)
-@internationalizeFunction('pluralize')
+@internationalizeFunction
def pluralize(s):
"""Returns the plural of s. Put any exceptions to the general English
rule of appending 's' in the plurals dictionary.
@@ -413,7 +439,7 @@
else:
return matchCase(s, s+'s')
-@internationalizeFunction('depluralize')
+@internationalizeFunction
def depluralize(s):
"""Returns the singular of s."""
consonants = 'bcdfghjklmnpqrstvwxz'
@@ -467,7 +493,7 @@
else:
return format('%s %s %s', n, between, item)
-@internationalizeFunction('ordinal')
+@internationalizeFunction
def ordinal(i):
"""Returns i + the ordinal indicator for the number.
@@ -486,7 +512,7 @@
ord = 'rd'
return '%s%s' % (i, ord)
-@internationalizeFunction('be')
+@internationalizeFunction
def be(i):
"""Returns the form of the verb 'to be' based on the number i."""
if i == 1:
@@ -494,7 +520,7 @@
else:
return 'are'
-@internationalizeFunction('has')
+@internationalizeFunction
def has(i):
"""Returns the form of the verb 'to have' based on the number i."""
if i == 1:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Limnoria-master-2022-03-19/test/test_callbacks.py
new/Limnoria-master-2022-07-03/test/test_callbacks.py
--- old/Limnoria-master-2022-03-19/test/test_callbacks.py 2022-03-17
22:29:10.000000000 +0100
+++ new/Limnoria-master-2022-07-03/test/test_callbacks.py 2022-06-23
22:31:17.000000000 +0200
@@ -634,6 +634,51 @@
finally:
self.irc.state.capabilities_ack.remove('message-tags')
+ def testClientTagReplyChannel(self):
+ self.irc.addCallback(self.First(self.irc))
+
+ try:
+ conf.supybot.protocols.irc.experimentalExtensions.setValue(True)
+ self.irc.state.capabilities_ack.add('message-tags')
+
+ # Reply in channel to channel message -> +draft/channel-context
+ # is absent
+ 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'}))
+
+ # Reply in private to channel message -> +draft/channel-context
+ # is present
+ with conf.supybot.reply.inPrivate.context(True):
+ 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='NOTICE', args=(self.nick, 'foo'),
+ server_tags={'+draft/reply': 'foobar',
+ '+draft/channel-context': '#foo'}))
+
+ # Reply in private to private message -> +draft/channel-context
+ # is absent
+ self.irc.feedMsg(ircmsgs.IrcMsg(
+ command='PRIVMSG', prefix=self.prefix,
+ args=(self.nick, 'firstcmd'),
+ server_tags={'msgid': 'foobar'}))
+ msg = self.irc.takeMsg()
+ self.assertEqual(msg, ircmsgs.IrcMsg(
+ command='NOTICE', args=(self.nick, 'foo'),
+ server_tags={'+draft/reply': 'foobar'}))
+ finally:
+ conf.supybot.protocols.irc.experimentalExtensions.setValue(False)
+ self.irc.state.capabilities_ack.remove('message-tags')
+
class TwoRepliesFirstAction(callbacks.Plugin):
def testactionreply(self, irc, msg, args):
irc.reply('foo', action=True)