#!/usr/bin/env python3 """ Reminds of things. """ import os import re from datetime import datetime, timedelta from collections import defaultdict import config import module def setup(bot): bot.db.execute("CREATE TABLE IF NOT EXISTS lazy_remind (" "nick TEXT," "datetime TIMESTAMP," "reminder TEXT)") lazy_reminds = bot.db.execute("SELECT * FROM lazy_remind").fetchall() bot.memory['lazy_remind'] = defaultdict(list) for remind in lazy_reminds: bot.memory['lazy_remind'][remind[0]].append(remind[1:3]) regex = ( "(?=\d+[ywdhms])" "(\d+y)?" "(\d+w)?" "(\d+d)?" "(\d+h)?" "(\d+m)?" "(\d+s)?" ) shorthand = { 'y': 'years', 'w': 'weeks', 'd': 'days', 'h': 'hours', 'm': 'minutes', 's': 'seconds', } @module.commands('remind') @module.example('.remind 3h45m Go to class') def remind(bot, trigger): """ Gives you a reminder in the given amount of time. -l, --lazy - Only activates the reminder when you speak. """ if len(trigger.args) == 1: return bot.msg("Missing arguments for reminder command.") if trigger.args[1] in ['-l', '--lazy']: if len(trigger.args) == 2: return bot.msg("Missing arguments for reminder command.") lazy = True trigger.args.pop(1) else: lazy = False reg = re.search(regex, trigger.args[1]) if not reg: return bot.reply("I didn't understand that.") args = {shorthand[g[-1]]: int(g[:-1]) for g in reg.groups() if g} delta = timedelta(**args) dt = datetime.now() + delta reminder = ' '.join(trigger.args[2:]) if lazy: bot.memory['lazy_remind'][trigger.nick].append((dt, reminder)) bot.db.execute("INSERT INTO lazy_remind VALUES(?,?,?)", (trigger.nick, dt, reminder)) else: args = (trigger.channel, trigger.nick, reminder) bot.scheduler.add_task(announce_reminder, dt, args) msg = "Okay, will " msg += "\x0310lazy\x03 " if lazy else "" msg += "remind at " msg+= dt.strftime('[%Y-%m-%d %H:%M:%S]') bot.reply(msg) @module.commands('at') @module.example('.at 2012-12-21 18:00:00 End the world.') def at(bot, trigger): """ Gives you a reminder at the given time and date. Datetime must be in YYYY-MM-DD HH:MM:SS format. Only the bot's timezone is used. If YYYY-MM-DD is excluded, it is assumed to be today's date. -l, --lazy - Only activates the reminder when you speak. """ if len(trigger.args) < 2: return bot.msg("Missing arguments for reminder command.") if trigger.args[1] in ['-l', '--lazy']: if len(trigger.args) < 3: return bot.msg("Missing arguments for reminder command.") lazy = True trigger.args.pop(1) else: lazy = False if ':' in trigger.args[1]: at_time = datetime.now().strftime('%Y-%m-%d') + ' ' + trigger.args[1] reminder = ' '.join(trigger.args[2:]) else: at_time = ' '.join(trigger.args[1:3]) reminder = ' '.join(trigger.args[3:]) try: dt = datetime.strptime(at_time, '%Y-%m-%d %H:%M:%S') except ValueError: return bot.msg("Datetime improperly formatted.") if lazy: bot.memory['lazy_remind'][trigger.nick].append((dt, reminder)) bot.db.execute("INSERT INTO lazy_remind VALUES(?,?,?)", (trigger.nick, dt, reminder)) else: args = (trigger.channel, trigger.nick, reminder) bot.scheduler.add_task(announce_reminder, dt, args) msg = "Okay, will " msg += "\x0310lazy\x03 " if lazy else "" msg += "remind at " msg+= dt.strftime('[%Y-%m-%d %H:%M:%S]') bot.reply(msg) def announce_reminder(bot, channel, remindee, reminder): """Announce the reminder.""" if reminder: msg = f"{remindee}: {reminder}" else: msg = f"{remindee}!" bot.msg(channel, msg) @module.hook(True) def lazy_remind(bot, trigger): """Lazy reminds only activate when the person speaks.""" if trigger.nick not in bot.memory['lazy_remind']: return due = [r for r in bot.memory['lazy_remind'][trigger.nick] if r[0] <= datetime.now()] if not due: return for remind in due: if remind[1]: bot.reply(remind[1]) else: bot.msg(trigger.nick + '!') bot.memory['lazy_remind'][trigger.nick].remove(remind) bot.db.execute("DELETE FROM lazy_remind " "WHERE nick = ? AND datetime = ? AND reminder = ?", (trigger.nick,) + tuple(remind))