#!/usr/bin/env python3 """ Allows the bot to scheduler tasks to be performed later. """ import time import pickle import threading from datetime import datetime class Scheduler: def __init__(self, bot): self.bot = bot self.tasks = [] self.lock = threading.Lock() self.init_database() self.load_database() self._t = threading.Thread(target=self.loop) self._t.start() def loop(self): while not self.bot.stillConnected(): time.sleep(1) while True: self.lock.acquire() tasks_due = [t for t in self.tasks if t[1] <= datetime.now()] for task in tasks_due: args = (self.bot,) + task[2] t = threading.Thread(target=task[0], args=args) t.start() self.tasks.remove(task) self.bot.db.execute( "DELETE FROM scheduled_task WHERE dt = ?", (pickle.dumps(task[1]),)) self.lock.release() time.sleep(5) def add_task(self, func, dt, args): """ `func` - The function to call. Must accept `bot` as the first argument. Must be picklable. `dt` - A datetime object representing when to call the function. `args` - Arguments to call the function with, not including `bot`. """ self.lock.acquire() self.tasks.append((func, dt, args)) self.lock.release() t = tuple(pickle.dumps(i) for i in (func, dt, args)) self.bot.db.execute("INSERT INTO scheduled_task VALUES (?,?,?)", t) def init_database(self): self.bot.db.execute("CREATE TABLE IF NOT EXISTS scheduled_task (" "func BLOB," "dt BLOB," "args BLOB" ")") def load_database(self): tasks = self.bot.db.execute("SELECT * FROM scheduled_task").fetchall() for task in tasks: t = tuple(pickle.loads(i) for i in task) self.tasks.append(t)