Redmine: Add announces support.

master
Valentin Lorentz 2012-12-15 22:16:37 +01:00
parent 8a58fd79ff
commit 73aa646f3d
3 changed files with 94 additions and 3 deletions

View File

@ -68,5 +68,15 @@ conf.registerChannelValue(Redmine.format, 'issue',
'\x02%(author__name)s\x02 (%(author__id)i) on \x02%(created_on)s\x02, '
'last updated on \x02%(updated_on)s',
_("""Format of issues displayed by @issue.""")))
conf.registerGroup(Redmine.format, 'announces')
conf.registerChannelValue(Redmine.format.announces, 'issue',
registry.String('Updated issue: \x02#%(id)i (%(status__name)s)\x02: '
'\x02%(subject)s\x02 in \x02%(project__name)s\x02 (%(project__id)i).',
_("""Format of issues displayed by @issue.""")))
conf.registerGroup(Redmine, 'announce')
conf.registerChannelValue(Redmine.announce, 'sites',
registry.SpaceSeparatedListOfStrings([],
_("""List of sites announced on this channel.""")))
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:

View File

@ -28,12 +28,15 @@
###
import sys
import json
import time
import supybot.conf as conf
import supybot.utils as utils
from supybot.commands import *
import supybot.plugins as plugins
import supybot.ircmsgs as ircmsgs
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
from supybot.i18n import PluginInternationalization, internationalizeDocstring
@ -149,6 +152,47 @@ class Redmine(callbacks.Plugin):
This should describe *how* to use this plugin."""
threaded = True
_last_fetch = {} # {site: (time, data)}
def __call__(self, irc, msg):
super(Redmine, self).__call__(irc, msg)
with self.registryValue('sites', value=False).editable() as sites:
assert isinstance(sites, dict), repr(sites)
for site_name, site in sites.items():
if 'interval' not in site:
site['interval'] = 60
if site_name in self._last_fetch:
last_time, last_data = self._last_fetch[site_name]
if last_time>time.time()-site['interval']:
continue
data = fetch(site, 'issues', sort='updated_on:desc')
self._last_fetch[site_name] = (time.time(), data)
if 'last_time' not in locals():
continue
try:
last_update = last_data['issues'][0]['updated_on']
except IndexError:
# There was no issue submitted before
last_update = ''
announces = []
for issue in data['issues']:
if issue['updated_on'] <= last_update:
break
announces.append(issue)
for channel in irc.state.channels:
if site_name in self.registryValue('announce.sites',
channel):
format_ = self.registryValue('format.announces.issue',
channel)
for issue in announces:
s = format_ % flatten_subdicts(issue)
if sys.version_info[0] < 3:
s = s.encode('utf8', errors='replace')
msg = ircmsgs.privmsg(channel, s)
irc.sendMsg(msg)
class site(callbacks.Commands):
conf = conf.supybot.plugins.Redmine
@internationalizeDocstring
@ -158,7 +202,7 @@ class Redmine(callbacks.Plugin):
Add a site to the list of known redmine sites."""
if not url.endswith('/'):
url += '/'
if name == '':
if not name:
irc.error(_('Invalid site name.'), Raise=True)
if name in self.conf.sites():
irc.error(_('This site name is already registered.'), Raise=True)

View File

@ -28,6 +28,9 @@
###
import time
import supybot.conf as conf
from supybot.test import *
def init(f):
@ -39,8 +42,8 @@ def init(f):
self.assertNotError('site remove lqdn')
return newf
class RedmineTestCase(PluginTestCase):
plugins = ('Redmine',)
class RedmineTestCase(ChannelPluginTestCase):
plugins = ('Redmine', 'Config', 'Utilities')
def testSite(self):
self.assertRegexp('site list', 'No registered')
@ -66,6 +69,40 @@ class RedmineTestCase(PluginTestCase):
self.assertNotError('issue lqdn 130')
self.assertResponse('issue lqdn 999999', 'Error: Issue not found.')
@init
def testAnnounce(self):
pl = self.irc.getCallback('Redmine')
self.assertNotError('ping')
self.assertNotError('config plugins.Redmine.announce.sites lqdn')
with conf.supybot.plugins.Redmine.sites.editable() as sites:
sites['lqdn']['interval'] = 1
# Make sure it does not update everytime a message is received
self.assertNotError('ping')
self.assertIs(self.irc.takeMsg(), None)
last_fetch = pl._last_fetch.copy()
self.assertNotError('ping')
self.assertEqual(last_fetch, pl._last_fetch)
self.assertIs(self.irc.takeMsg(), None)
# Make sure it updates after the interval is finished, but there is
# nothing new
time.sleep(1.1)
self.assertNotError('ping')
self.assertNotEqual(last_fetch, pl._last_fetch)
self.assertIs(self.irc.takeMsg(), None)
# Let's cheat a little and "olderize" the latest issue.
pl._last_fetch['lqdn'][1]['issues'][0]['updated_on'] = \
'2012/12/09 20:37:27 +0100'
time.sleep(1.1)
self.assertNotError('ping')
self.assertNotEqual(last_fetch, pl._last_fetch)
m = self.irc.takeMsg()
self.assertIsNot(m, None)
if not network:
del RedmineTestCase