async def task_reset(self, bot): """ The scheduled task to reset user goals at midnight :param bot: :return: """ # Find all the user_goal records which are due a reset now = int(time.time()) records = self.__db.get_all_sql( 'SELECT * FROM user_goals WHERE reset <= %s', [now]) for record in records: # Calculate the next reset time for the goal, depending on its type. user = User(record['user'], 0) try: next = user.calculate_user_reset_time(record['type']) lib.debug('Setting next ' + record['type'] + ' goal reset time for ' + str(record['user']) + ' to: ' + str(next)) self.__db.update('user_goals', { 'completed': 0, 'current': 0, 'reset': next }, {'id': record['id']}) except pytz.exceptions.UnknownTimeZoneError: lib.out('[ERROR] Invalid timezone (' + user.get_setting('timezone') + ') for user ' + str(record['user'])) return True
async def scheduled_tasks(self): """ Execute the scheduled tasks. (I believe) this is going to happen for each shard, so if we have 5 shards for example, this loop will be running simultaneously on each of them. :return: """ lib.debug('[' + str(self.shard_id) + '] Checking for scheduled tasks...') try: await Task.execute_all(self) except Exception as e: lib.out('Exception: ' + str(e))
def update(self): """ Run any database updates which are required :return: """ db = Database.instance() version = lib.get('./version.json') version = version.db_version db_version = db.get('bot_settings', {'setting': 'version'}) current_version = db_version['value'] if db_version else 0 version = int(version) current_version = int(current_version) # Find all update files for file in os.listdir(f'data/updates'): # If it ends with .update then try to use it. if file.endswith(".update"): # Get the update version from the file name and convert to int for comparison. update_version = int(file[:-7]) # Is this update due to run? if update_version > current_version: # Load the file and the SQL to run. update = lib.get('./data/updates/' + file) # Loop through the array of SQL statements to run. for sql in update: lib.out('[UPDATE] Running query `' + sql + '`') db.execute(sql, []) # Once it's done, update the version in the database. setting = db.get('bot_settings', {'setting': 'version'}) if setting: db.update('bot_settings', {'value': version}, {'setting': 'version'}) else: db.insert('bot_settings', {'setting': 'version', 'value': version})
async def task_reset(self, bot): """ The scheduled task to reset user goals at midnight :param bot: :return: """ # Find all the user_goal records which are due a reset now = int(time.time()) records = self.__db.get_all_sql( 'SELECT * FROM user_goals WHERE reset <= %s', [now]) for record in records: # Calculate the next reset time for the goal, depending on its type. user = User(record['user'], 0) try: user.reset_goal(record) except pytz.exceptions.UnknownTimeZoneError: lib.out('[ERROR] Invalid timezone (' + user.get_setting('timezone') + ') for user ' + str(record['user'])) return True
def load_commands(self): """ Load all the commands from the cogs/ directory. :return: void """ # Find all the command groups in the cogs/ directory for dir in self.COMMAND_GROUPS: # Then all the files inside the command group directory for file in os.listdir(f'cogs/{dir}'): # If it ends with .py then try to load it. if file.endswith(".py"): cog = file[:-3] try: self.load_extension(f"cogs.{dir}.{cog}") lib.out(f'[EXT][{dir}.{cog}] loaded') except Exception as e: lib.out(f'[EXT][{dir}.{cog}] failed to load') lib.out(e)
def setup(self): """ Run the bot setup :return: """ lib.out('[BOT] Beginning boot process') # Install the database. db = Database.instance() db.install() lib.out('[DB] Database tables installed') # Run any database updates. self.update() # Setup the recurring tasks which need running. self.setup_recurring_tasks() lib.out('[TASK] Recurring tasks inserted') # Restart all tasks which are marked as processing, in case the bot dropped out during the process. db.update('tasks', {'processing': 0}) # Remove the default 'help' command. self.remove_command('help')
async def run(self, bot): """ Run this task TODO: In the future, make this better. For now it will do. :return: bool """ # If the task is already processing, don't go any further. if self.is_processing(): return True # Mark the task as processing so other shards don't pick it up. self.start_processing(1) # Build a variable to store the method name to run method = 'task_' + str(self.type) # Start off with a False and see if we can successfully run and turn that to True result = False # Sprint tasks. if self.object == 'sprint': from structures.sprint import Sprint sprint = Sprint.get(self.object_id) if sprint.is_valid(): result = await getattr(sprint, method)(bot) else: # If the sprint doesn't exist, then we can just delete this task. result = True elif self.object == 'goal': from structures.goal import Goal goal = Goal() result = await getattr(goal, method)(bot) elif self.object == 'event': from structures.event import Event event = Event(self.object_id) if event.is_valid(): result = await getattr(event, method)(bot) else: # If the event doesn't exist, then we can just delete this task. return True else: # Invalid task object. May as well just delete this task. lib.out('Invalid task object: ' + self.object) result = True # If we finished the task, and it's not a recurring one, delete it. if result is True and not self.is_recurring(): self.delete() else: self.start_processing(0) # If it's a recurring task, set its next run time. if self.is_recurring(): self.set_recur() return result