import discord import pickle from discord.ext import commands, tasks from dateutil.rrule import * from dateutil.parser import * from dateutil.tz import gettz from datetime import datetime class TrackTimer(): 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 self.what def __eq__(self, other): return self.id == other def valid(self): 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(): 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 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))