"""Access to countdown items through bot commands.""" import logging import threading import time from dateutil.relativedelta import relativedelta from django.utils import timezone from ircbot.lib import Plugin from countdown.models import CountdownItem log = logging.getLogger('countdown.ircplugin') class Countdown(Plugin): """Report on countdown items.""" def __init__(self, bot, connection, event): """Initialize some stuff.""" self.running_reminders = [] self.send_reminders = True t = threading.Thread(target=self.reminder_thread) t.daemon = True t.start() super(Countdown, self).__init__(bot, connection, event) def start(self): """Set up handlers.""" self.running_reminders = [] self.send_reminders = True self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!countdown\s+list$', self.handle_item_list, -20) self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!countdown\s+(\S+)$', self.handle_item_detail, -20) super(Countdown, self).start() def stop(self): """Tear down handlers.""" self.running_reminders = [] self.send_reminders = False self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_item_list) self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_item_detail) super(Countdown, self).stop() def reminder_thread(self): """After IRC is started up, begin sending reminders.""" time.sleep(30) while self.send_reminders: reminders = CountdownItem.objects.filter(is_reminder=True, sent_reminder=False) for reminder in reminders: log.debug("%s @ %s", reminder.reminder_message, reminder.at_time) if reminder.at_time <= timezone.now(): log.info("sending %s to %s", reminder.reminder_message, reminder.reminder_target) self.bot.reply(None, reminder.reminder_message, explicit_target=reminder.reminder_target) reminder.sent_reminder = True reminder.save() time.sleep(1) def handle_item_detail(self, connection, event, match): """Provide the details of one countdown item.""" name = match.group(1) if name != 'list': try: item = CountdownItem.objects.get(name=name) rdelta = relativedelta(item.at_time, timezone.now()) relstr = "{0:s} will occur in ".format(name) if rdelta.years != 0: relstr += "{0:s} year{1:s} ".format(str(rdelta.years), "s" if abs(rdelta.years) != 1 else "") if rdelta.months != 0: relstr += "{0:s} month{1:s}, ".format(str(rdelta.months), "s" if abs(rdelta.months) != 1 else "") if rdelta.days != 0: relstr += "{0:s} day{1:s}, ".format(str(rdelta.days), "s" if abs(rdelta.days) != 1 else "") if rdelta.hours != 0: relstr += "{0:s} hour{1:s}, ".format(str(rdelta.hours), "s" if abs(rdelta.hours) != 1 else "") if rdelta.minutes != 0: relstr += "{0:s} minute{1:s}, ".format(str(rdelta.minutes), "s" if abs(rdelta.minutes) != 1 else "") if rdelta.seconds != 0: relstr += "{0:s} second{1:s}, ".format(str(rdelta.seconds), "s" if abs(rdelta.seconds) != 1 else "") # remove trailing comma from output reply = relstr[0:-2] return self.bot.reply(event, reply) except CountdownItem.DoesNotExist: return self.bot.reply(event, "countdown item '{0:s}' not found".format(name)) def handle_item_list(self, connection, event, match): """List all countdown items.""" items = CountdownItem.objects.all() if len(items) > 0: reply = "countdown items: {0:s}".format(", ".join([x.name for x in items])) return self.bot.reply(event, reply) else: return self.bot.reply(event, "no countdown items are configured") plugin = Countdown