async def end(self, context=None, bot=None): """ Mark the 'end' time of the sprint as 0 in the database and ask for final word counts :return: """ # End the sprint in the database self.set_ended() if bot is None: bot = self.bot # Get the sprinting users to notify notify = self.get_notifications(self.get_users()) # Check for a guild setting for the delay time, otherwise use the default guild = Guild.get_from_bot(bot, self._guild) delay = guild.get_setting('sprint_delay_end') if delay is None: delay = self.DEFAULT_POST_DELAY # Post the ending message message = lib.get_string('sprint:end', self._guild).format(delay) message = message + ', '.join(notify) await self.say(message, context, bot) # Convert the minutes to seconds delay = int(delay) * 60 task_time = int(time.time()) + delay # Schedule the cron task Task.schedule(self.TASKS['complete'], task_time, 'sprint', self._id)
async def run_start(self, context, length=None, start=None): """ Try to start a sprint on the server :param context :param length: Length of time (in minutes) the sprint should last :param start: Time in minutes from now, that the sprint should start :return: """ user = User(context.message.author.id, context.guild.id, context) sprint = Sprint(user.get_guild()) # Check if sprint is finished but not marked as completed, in which case we can mark it as complete if sprint.is_finished(): # Mark the sprint as complete await sprint.complete() # Reload the sprint object, as now there shouldn't be a pending one sprint = Sprint(user.get_guild()) # If a sprint is currently running, we cannot start a new one if sprint.exists(): return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:alreadyexists', user.get_guild())) # Must be okay to continue # # If the length argument is not valid, use the default if length is None or lib.is_number(length) is False or lib.is_number(length) <= 0 or lib.is_number(length) > self.MAX_LENGTH: length = self.DEFAULT_LENGTH # Same goes for the start argument if start is None or lib.is_number(start) is False or lib.is_number(start) < 0 or lib.is_number(start) > self.MAX_DELAY: start = self.DEFAULT_DELAY # Make sure we are using ints and not floats passed through in the command length = int(length) start = int(start) # Calculate the start and end times based on the current timestamp now = int(time.time()) start_time = now + (start * 60) end_time = start_time + (length * 60) # Create the sprint sprint = Sprint.create(guild=user.get_guild(), channel=context.message.channel.id, start=start_time, end=end_time, end_reference=end_time, length=length, createdby=user.get_id(), created=now) # Join the sprint sprint.join(user.get_id()) # Increment the user's stat for sprints created user.add_stat('sprints_started', 1) # Are we starting immediately or after a delay? if start == 0: # Immediately. That means we need to schedule the end task. Task.schedule(sprint.TASKS['end'], end_time, 'sprint', sprint.get_id()) return await sprint.post_start(context) else: # Delay. That means we need to schedule the start task, which will in turn schedule the end task once it's run. Task.schedule(sprint.TASKS['start'], start_time, 'sprint', sprint.get_id()) return await sprint.post_delayed_start(context)
async def task_start(self, bot) -> bool: """ Scheduled task to start the sprint :param task: :return: bool """ # Run pre-checks if not self._task_prechecks(bot): return True now = int(time.time()) # If the sprint has already finished, we don't need to do anything so we can return True and just have the task deleted. if self.is_finished() or self.is_complete(): return True # Post the starting message. await self.post_start(bot=bot) # Schedule the end task. Task.schedule(self.TASKS['end'], self._end, 'sprint', self._id) return True
async def run_schedule(self, context): """ Schedule the event to start and end at a specific datetime :param context: :return: """ user = User(context.message.author.id, context.guild.id, context) event = Event.get_by_guild(user.get_guild()) # Do they have the permissions to rename an event? self.check_permissions(context) # Make sure the event is running if event is None: return await context.send( user.get_mention() + ', ' + lib.get_string('event:err:noexists', user.get_guild())) # Make sure the event is running if event.is_running(): return await context.send( user.get_mention() + ', ' + lib.get_string('event:err:alreadyrunning', user.get_guild())) # Do they have a timezone set in their user settings? user_timezone = user.get_setting('timezone') if user_timezone is None: return await context.send( user.get_mention() + ', ' + lib.get_string('event:err:timezonenotset', user.get_guild())) timezone = pytz.timezone(user_timezone) time = datetime.now(timezone).strftime('%H:%M:%S') offset = datetime.now(timezone).strftime('%z') # Print the pre-schedule information to check their timezone is correct. await context.send(user.get_mention() + ', ' + lib.get_string('event:preschedule', user.get_guild( )).format(user_timezone, time, offset)) # We now have various stages to go through, so we loop through the stages, ask the question and store the user input as the answer. answers = [] # Stage 1 - Start date answer = await self.run_stage_one(context) if not answer: return answers.append({'stage': 1, 'answer': answer}) # Stage 2 - Start time answer = await self.run_stage_two(context) if not answer: return answers.append({'stage': 2, 'answer': answer}) # Stage 3 - End date answer = await self.run_stage_three(context) if not answer: return answers.append({'stage': 3, 'answer': answer}) # Stage 4 - End time answer = await self.run_stage_four(context) if not answer: return answers.append({'stage': 4, 'answer': answer}) # Stage 5 - Confirmation answer = await self.run_stage_five(context, answers) if not answer: return answers.append({'stage': 5, 'answer': answer}) # Now run the checks to make sure the end date is later than start date, etc... check = await self.check_answers(context, answers) if not check: return # Now convert those start and end times to UTC timestamps start = datetime.strptime( lib.find(answers, 'stage', 1)['answer'] + ' ' + lib.find(answers, 'stage', 2)['answer'], '%d-%m-%Y %H:%M') end = datetime.strptime( lib.find(answers, 'stage', 3)['answer'] + ' ' + lib.find(answers, 'stage', 4)['answer'], '%d-%m-%Y %H:%M') adjusted_start = int(timezone.localize(start).timestamp()) adjusted_end = int(timezone.localize(end).timestamp()) # Schedule the event with those timestamps event.set_startdate(adjusted_start) event.set_enddate(adjusted_end) event.set_channel(context.message.channel.id) event.save() # Remove any tasks we already had saved for this event. Task.cancel('event', event.get_id()) # Schedule the tasks to run at those times. Task.schedule(Event.TASKS['start'], event.get_start_time(), 'event', event.get_id()) Task.schedule(Event.TASKS['end'], event.get_end_time(), 'event', event.get_id()) return await context.send( user.get_mention() + ', ' + lib.get_string('event:scheduled', user.get_guild()).format( event.get_title(), start, end))