Redmine: Add announces support.
parent
8a58fd79ff
commit
73aa646f3d
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue