diff --git a/Timer.py b/Timer.py index b4b0fe9..76bbca0 100644 --- a/Timer.py +++ b/Timer.py @@ -1,48 +1,121 @@ import discord +import pickle from discord.ext import commands, tasks -import time +from dateutil.rrule import * +from dateutil.parser import * +from dateutil.tz import gettz +from datetime import datetime class TrackTimer(): - def __init__(self, duration, users, channel, author): - self.end = time.time() + duration - self.users = users + def __init__(self, id, what, when, channel, author): + self.id = id + + self.what = what + self.when = when + self.channel = channel self.author = author + self.remind = next(self.when) + self.tz = self.remind.tzinfo + self.validate() def __str__(self): - return str(self.end - time.time()) + "s remaining." + return self.what + def __eq__(self, other): + return self.id == other def valid(self): - return time.time() < (self.end) + return datetime.now(self.tz) < (self.remind) + def validate(self): + while not self.valid(): + self.remind = next(self.when) + def status(self): + return f"I'm going to tell {self.author.display_name} to {self.what.replace(' my ', ' their ')} at {self.remind}" + def next(self): + self.remind = next(self.when) + return f"I'm going to tell you again at {self.remind}" + def shout(self): + return f"Hey {self.author.mention}! **Go {self.what.replace(' my ', ' your ')}!**" + +class PickleTimer(): + def __init__(self, id, what, when, ctx): + self.id = id + self.what = what + self.when = when + self.channel = ctx.channel.id + self.author = ctx.author.id + try: + self.guild = ctx.channel.guild.id + except: + pass + def __eq__(self, other): + return self.id == other class Timer(commands.Cog): """Timer commands.""" def __init__(self, bot): self.bot = bot + self.id = 1 self.check_timers.start() self.timers = [] + self.pickle_timers = [] + self.tz = {"AWST": gettz("Australia/Perth"), "ACWST": gettz("Australia/Eucla")} + + @commands.Cog.listener() + async def on_ready(self): + await self.bot.wait_until_ready() + file = open('timerlist', 'rb') + self.pickle_timers = pickle.load(file) + for timer in self.pickle_timers: + if timer.id >= self.id: + self.id = timer.id + 1 + t_timer = await self.tracked_timer(timer) + t_timer.validate() + self.timers.append(t_timer) + + async def tracked_timer(self, pt): + channel = await self.bot.fetch_channel(pt.channel) + user = await self.bot.fetch_user(pt.author) + repeat_rule = rrule(DAILY, parse(pt.when, fuzzy=True, tzinfos=self.tz)) + return TrackTimer(pt.id, pt.what, iter(repeat_rule), channel, user) @tasks.loop(seconds=2.0) async def check_timers(self): for timer in self.timers: if not timer.valid(): - msg = "Pencils down! " - msg += timer.author.mention + " " - for user in timer.users: - msg += user.mention + " " - await timer.channel.send(msg) - self.timers.remove(timer) + await timer.channel.send(f"{timer.shout()} {timer.next()}") + + def save(self): + with open('timerlist', 'wb') as file: + pickle.dump(self.pickle_timers, file) @commands.command(pass_context=True, hidden=False) - async def timer(self, ctx, minutes: int, mentions: str): - """Starts a timer for a given number of minutes. - Tags mentioned users when timer expires. - Always tags the user that called this function""" - self.timers.append(TrackTimer(minutes*60, ctx.message.mentions, ctx.channel, ctx.author)) - msg = "Okay " - for user in ctx.message.mentions: - msg += user.display_name + ", " - msg += ctx.author.display_name + "; " - msg += "your " + str(minutes) + " minutes start now." + async def remindme(self, ctx, what: str, *when: str,): + try: + when = " ".join(when) + repeat_rule = rrule(DAILY, parse(when, fuzzy=True, tzinfos=self.tz)) + timer = TrackTimer(self.id, what, iter(repeat_rule), ctx.channel, ctx.author) + self.pickle_timers.append(PickleTimer(self.id, what, when, ctx)) + self.timers.append(timer) + self.id += 1 + msg = f"Fine. {timer.status()}" + self.save() + await ctx.channel.send(msg) + except Exception as e: + await ctx.channel.send(f"You idiot. Send the command right: {e}") + + @commands.command(pass_context=True, hidden=False) + async def reminders(self, ctx): + msg = "Here are my current reminders:\n" + for timer in self.timers: + msg += f"\t{timer.id}:\t{timer.status()}\n" + msg += "Use `!delete ` to delete a standing reminder" await ctx.channel.send(msg) + @commands.command(pass_context=True, hidden=False) + async def delete(self, ctx, id: int): + self.timers.remove(id) + self.pickle_timers.remove(id) + self.save() + await ctx.channel.send(f"Fine. Deleting reminder {id}..") + def setup(bot): bot.add_cog(Timer(bot))