aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoachim Filip Ignacy Bartosik <jbartosik@gmail.com>2011-06-22 09:28:20 +0200
committerJoachim Filip Ignacy Bartosik <jbartosik@gmail.com>2011-06-22 20:31:35 +0200
commit62b3ba6efe4ac1de77f24527e844c9a70ed94b1b (patch)
tree10b735cb58d407ddcbd32a97bdfc68eb8eab0de6
parentMerge remote-tracking branch 'github/new_bot_commands' (diff)
downloadcouncil-webapp-62b3ba6efe4ac1de77f24527e844c9a70ed94b1b.tar.gz
council-webapp-62b3ba6efe4ac1de77f24527e844c9a70ed94b1b.tar.bz2
council-webapp-62b3ba6efe4ac1de77f24527e844c9a70ed94b1b.zip
Add support for #timelimit (add|list|remove) commands
-rw-r--r--bot/ircmeeting/agenda.py46
-rw-r--r--bot/ircmeeting/meeting.py17
-rw-r--r--bot/tests/run_test.py56
3 files changed, 116 insertions, 3 deletions
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index 928ff5f..220acf9 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -1,7 +1,15 @@
import json
+import threading
import urllib
import re
+class MessageSender:
+ def __init__(self, irc, message):
+ self.irc = irc
+ self.message = message
+ def send_message(self):
+ self.irc.reply(self.message)
+
class Agenda(object):
# Messages
@@ -18,6 +26,10 @@ class Agenda(object):
not_a_number_msg = "Your vote was not recognized as a number. Please retry."
out_of_range_msg = "Your vote was out of range!"
vote_confirm_msg = "You voted for #{} - {}"
+ timelimit_added_msg = 'Added "{}" reminder in {}:{}'
+ timelimit_list_msg = 'Set reminders: "{}"'
+ timelimit_removed_msg = 'Reminder "{}" removed'
+ timelimit_missing_msg = 'No such reminder "{}"'
# Internal
_voters = []
@@ -28,6 +40,7 @@ class Agenda(object):
def __init__(self, conf):
self.conf = conf
+ self.reminders = {}
def get_agenda_item(self):
if not self.conf.manage_agenda:
@@ -37,6 +50,12 @@ class Agenda(object):
else:
return self.empty_agenda_msg
+ def _swich_agenda_item_to(self, new_item):
+ self._current_item = new_item
+ for reminder in self.reminders.values():
+ reminder.cancel()
+ self.reminders = {}
+
def next_agenda_item(self):
if not self.conf.manage_agenda:
return('')
@@ -44,7 +63,7 @@ class Agenda(object):
return self.voting_open_so_item_not_changed_msg
else:
if (self._current_item + 1) < len(self._agenda):
- self._current_item += 1
+ self._swich_agenda_item_to(self._current_item + 1)
return(self.get_agenda_item())
def prev_agenda_item(self):
@@ -54,7 +73,7 @@ class Agenda(object):
return self.voting_open_so_item_not_changed_msg
else:
if self._current_item > 0:
- self._current_item -= 1
+ self._swich_agenda_item_to(self._current_item - 1)
return(self.get_agenda_item())
def start_vote(self):
@@ -144,6 +163,29 @@ class Agenda(object):
option = self._agenda[self._current_item][1].pop(opt)
return str.format(self.removed_option_msg, str(opt), option)
+ def add_timelimit(self, minutes, seconds, message, irc):
+ sender = MessageSender(irc, message)
+ reminder = (threading.Timer(60*minutes + seconds, sender.send_message))
+ self.reminders[message] = reminder
+ reminder.start()
+ result = str.format(self.timelimit_added_msg, message, minutes, seconds)
+ return(result)
+
+ def list_timielimits(self):
+ keys = self.reminders.keys()
+ keys_str = '", "'.join(keys)
+ result = str.format(self.timelimit_list_msg, keys_str)
+ return(result)
+
+ def remove_timelimit(self, message):
+ if message in self.reminders:
+ timer = self.reminders.pop(message)
+ timer.cancel()
+ result = str.format(self.timelimit_removed_msg, message)
+ else:
+ result = str.format(self.timelimit_missing_msg, message)
+ return(result)
+
def post_result(self):
if not self.conf.manage_agenda:
return('')
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index 84949ed..4bd3221 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -33,6 +33,7 @@ import time
import os
import re
import stat
+import threading
import writers
import items
@@ -301,7 +302,6 @@ else:
# Subclass Config and LocalConfig, new type overrides Config.
Config = type('Config', (LocalConfig, Config), {})
-
class MeetingCommands(object):
# Command Definitions
# generic parameters to these functions:
@@ -328,6 +328,21 @@ class MeetingCommands(object):
def do_previtem(self, nick, time_, line, **kwargs):
self.reply(self.config.agenda.prev_agenda_item())
+ def do_timelimit(self, nick, time_, line, **kwargs):
+ reply = 'Usage "#timelimit add <minutes>:<seconds> <message>" or ' +\
+ '"#timelimit list" or "#timelimit remove <message>"'
+ match = re.match( ' *?add ([0-9]+):([0-9]+) (.*)', line)
+ if match:
+ reply = self.config.agenda.add_timelimit(int(match.group(1)),
+ int(match.group(2)), match.group(3), self)
+ elif re.match( ' *?list', line):
+ reply = self.config.agenda.list_timielimits()
+ else:
+ match = re.match( ' *?remove (.*)', line)
+ if(match):
+ reply = self.config.agenda.remove_timelimit(match.group(1))
+ self.reply(reply)
+
def do_startvote(self, nick, time_, line, **kwargs):
for messageline in self.config.agenda.start_vote().split('\n'):
self.reply(messageline)
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index 9808ee6..e3a9030 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -6,6 +6,8 @@ import re
import shutil
import sys
import tempfile
+import time
+import threading
import unittest
os.environ['MEETBOT_RUNNING_TESTS'] = '1'
@@ -427,6 +429,60 @@ class MeetBotTest(unittest.TestCase):
assert(test.votes() == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}})
+ def test_agenda_time_limit_adding(self):
+ test = self.get_simple_agenda_test()
+ test.answer_should_match('20:13:50 <x> #timelimit', 'Usage "#timelimit ' +\
+ 'add <minutes>:<seconds> <message>" or "' +\
+ '#timelimit list" or "#timelimit remove ' +\
+ '<message>"')
+ test.answer_should_match('20:13:50 <x> #timelimit add 0:1 some other message',
+ 'Added "some other message" reminder in 0:1')
+ test.answer_should_match('20:13:50 <x> #timelimit add 1:0 some message',
+ 'Added "some message" reminder in 1:0')
+ time.sleep(2)
+ last_message = test.log[-1]
+ assert(last_message == 'some other message')
+ reminders = test.M.config.agenda.reminders
+ assert(len(reminders) == 2)
+ for reminder in reminders.values():
+ assert(reminder.__class__ == threading._Timer)
+
+ test.process('20:13:50 <x> #nextitem')
+
+ def test_agenda_time_limit_removing_when_changing_item(self):
+ test = self.get_simple_agenda_test()
+
+ test.process('20:13:50 <x> #timelimit add 0:1 message')
+ assert(len(test.M.config.agenda.reminders) == 1)
+ test.process('20:13:50 <x> #nextitem')
+ assert(len(test.M.config.agenda.reminders) == 0)
+ test.process('20:13:50 <x> #timelimit add 0:1 message')
+ assert(len(test.M.config.agenda.reminders) == 1)
+ test.process('20:13:50 <x> #previtem')
+ assert(len(test.M.config.agenda.reminders) == 0)
+
+ def test_agenda_time_limit_manual_removing(self):
+ test = self.get_simple_agenda_test()
+
+ test.process('20:13:50 <x> #timelimit add 0:1 message')
+ test.process('20:13:50 <x> #timelimit add 0:1 other message')
+ keys = test.M.config.agenda.reminders.keys()
+ keys.sort()
+ assert(keys == ['message', 'other message'])
+
+ test.answer_should_match('20:13:50 <x> #timelimit remove other message', 'Reminder "other message" removed')
+ keys = test.M.config.agenda.reminders.keys()
+ assert(keys == ['message'])
+
+ def test_agenda_time_limit_listing(self):
+ test = self.get_simple_agenda_test()
+ test.process('20:13:50 <x> #timelimit add 0:1 message')
+ test.process('20:13:50 <x> #timelimit add 0:1 other message')
+ test.process('20:13:50 <x> #timelimit add 0:1 yet another message')
+ keys = test.M.config.agenda.reminders.keys()
+ test.answer_should_match('20:13:50 <x> #timelimit list',
+ 'Set reminders: "' + '", "'.join(keys) + '"')
+
if __name__ == '__main__':
os.chdir(os.path.join(os.path.dirname(__file__), '.'))