From 9af77b99b6c76712c77538b8c2c74f309650189a Mon Sep 17 00:00:00 2001 From: iou1name Date: Mon, 29 Jun 2020 14:59:24 -0400 Subject: [PATCH] refactor lazy remind, add recurring remind --- modules/remind.py | 145 ++++++++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 62 deletions(-) diff --git a/modules/remind.py b/modules/remind.py index df8c1a8..b7c5079 100755 --- a/modules/remind.py +++ b/modules/remind.py @@ -7,18 +7,12 @@ import re from datetime import datetime, timedelta from collections import defaultdict +import tools 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])" @@ -40,43 +34,68 @@ shorthand = { @module.commands('remind') @module.example('.remind 3h45m Go to class') -def remind(bot, trigger): +def remind_recur(bot, trigger): """ - Gives you a reminder in the given amount of time. + Sets a recurring reminder. + -s, --start - Starts the cycle at the given point in time instead of now. -l, --lazy - Only activates the reminder when you speak. + -r, --recur - Repeats the reminder every given period. """ - 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 + if len(trigger.args) < 2: + return bot.msg("Missing arguments.") - 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} - if args.get('years'): - args['days'] = args['years']*365 + args.get('days', 0) # screw leap years - del args['years'] - 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)) + parser = tools.FulviaArgparse() + parser.add_argument('period') + parser.add_argument('reminder', nargs='*') + parser.add_argument('-s', '--start') + parser.add_argument('-l', '--lazy', action='store_true') + parser.add_argument('-r', '--recur', action='store_true') + try: + args = parser.parse_args(trigger.args[1:]) + except Exception as e: + return bot.reply(type(e).__name__ + ": " + str(e)) + + if args.start: + try: + start = datetime.strptime(args.start, '%Y-%m-%d %H:%M:%S') + except ValueError: + return bot.msg("Datetime improperly formatted.") else: - args = (trigger.channel, trigger.nick, reminder) - bot.scheduler.add_task(announce_reminder, dt, args) + start = datetime.now() + + reg = re.search(regex, args.period) + if not reg: + return bot.reply("I didn't understand that time period.") + parts = {shorthand[g[-1]]: int(g[:-1]) for g in reg.groups() if g} + if parts.get('years'): + parts['days'] = parts['years']*365 + parts.get('days', 0) # screw leap years + del parts['years'] + delta = timedelta(**parts) + sched_time = start + delta + + reminder = ' '.join(args.reminder) + if reminder: + reminder = trigger.nick + ': ' + reminder + else: + reminder = trigger.nick + '!' + + if args.recur: + recur = delta + else: + recur = None + + if args.lazy: + sched_args = (trigger.nick, reminder, recur) + bot.scheduler.add_task(announce_lazy_reminder, sched_time, sched_args) + else: + sched_args = (trigger.channel, trigger.nick, reminder, recur) + bot.scheduler.add_task(announce_reminder, sched_time, sched_args) + msg = "Okay, will " - msg += "\x0310lazy\x03 " if lazy else "" + msg += "\x0310lazy\x03 " if args.lazy else "" msg += "remind at " - msg+= dt.strftime('[%Y-%m-%d %H:%M:%S]') + msg+= sched_time.strftime('[%Y-%m-%d %H:%M:%S]') bot.reply(msg) @@ -106,48 +125,50 @@ def at(bot, trigger): at_time = ' '.join(trigger.args[1:3]) reminder = ' '.join(trigger.args[3:]) + if reminder: + reminder = trigger.nick + ': ' + reminder + else: + reminder = trigger.nick + '!' + try: - dt = datetime.strptime(at_time, '%Y-%m-%d %H:%M:%S') + sched_time = 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)) + sched_args = (trigger.nick, reminder) + bot.scheduler.add_task(announce_lazy_reminder, sched_time, sched_args) else: - args = (trigger.channel, trigger.nick, reminder) - bot.scheduler.add_task(announce_reminder, dt, args) + sched_args = (trigger.channel, trigger.nick, reminder) + bot.scheduler.add_task(announce_reminder, sched_time, sched_args) msg = "Okay, will " msg += "\x0310lazy\x03 " if lazy else "" msg += "remind at " - msg+= dt.strftime('[%Y-%m-%d %H:%M:%S]') + msg+= sched_time.strftime('[%Y-%m-%d %H:%M:%S]') bot.reply(msg) -def announce_reminder(bot, channel, remindee, reminder): +def announce_reminder(bot, channel, remindee, reminder, delta=None): """Announce the reminder.""" - if reminder: - msg = f"{remindee}: {reminder}" - else: - msg = f"{remindee}!" - bot.msg(channel, msg) + bot.msg(channel, reminder) + if delta: + sched_time = datetime.now() + delta + args = (channel, remindee, reminder, delta) + bot.scheduler.add_task(announce_reminder, sched_time, args) + + +def announce_lazy_reminder(bot, remindee, reminder, delta=None): + """Announce the reminder.""" + bot.memory['lazy_remind'][remindee].append(reminder) + if delta: + sched_time = datetime.now() + delta + args = (remindee, reminder, delta) + bot.scheduler.add_task(announce_lazy_reminder, sched_time, args) @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 + '!') + for remind in bot.memory['lazy_remind'].get(trigger.nick, []): + bot.msg(remind) 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))